Swift allSatisfy: Check That Every Element Passes a Test
Before you drive a car, one failed check is enough to stop you. A flat battery does not care that the tyres, oil, and fuel are all fine. The allSatisfy(_:) method asks that same question of a Swift collection and gives you a single yes or no:
let pressures = [32, 30, 0, 33]
print(pressures.allSatisfy { $0 > 0 }) // Program output:
// false Syntax and What It Returns
The method lives on Sequence, so every array, set, dictionary, and range has it. It takes one closure and returns a Bool:
func allSatisfy(_ predicate: (Element) throws -> Bool) rethrows -> Bool The predicate parameter is called once per element and answers whether that element passes. The result is true only when every call answered true. The rethrows keyword means the call throws only if your closure does.
It also short-circuits. The moment a call returns false, the method stops and returns false without touching the rest of the collection.
Validating a Collection of Values
The most common use is a guard over simple values. Both arrays and sets work, since neither ordering nor duplicates change the answer:
let names = ["John", "Ethan", "Jason"]
print(names.allSatisfy { $0.hasSuffix("n") })
let scores: Set = [88, 95, 72, 80]
print(scores.allSatisfy { $0 >= 70 })
let stock = [25, 50, 0, 40]
print(stock.allSatisfy { $0 > 0 }) // Program output:
// true
// true
// false Each line reads close to the sentence you would say out loud. The third one is the interesting case: it stops at the zero and never looks at the 40 behind it.
Validating a Collection of Structs
The method earns more of its keep on modelled data, where the closure names a property instead of comparing the whole element:
struct SensorReading {
let measurement: Double
let isAccurate: Bool
}
let readings = [
SensorReading(measurement: 25.3, isAccurate: true),
SensorReading(measurement: 30.1, isAccurate: true),
SensorReading(measurement: 29.8, isAccurate: false),
]
let usable = readings.allSatisfy { $0.isAccurate && $0.measurement > 0 }
print(usable ? "Ready to process." : "Check the sensors.") // Program output:
// Check the sensors. Two conditions combine inside one closure, which is fine while they still read as one rule. Once a predicate needs three lines and a comment, move it to a named method on the element type and call that instead.
Why does an empty collection return true?
This is the behaviour that surprises people, and it is deliberate. With no elements present, there is no element that fails, so the honest answer to "do all of them pass?" is yes:
let noTyres: [Int] = []
print(noTyres.allSatisfy { $0 > 0 }) // Program output:
// true Logicians call that vacuous truth, and it is the standard definition behind universal-predicate operations in other languages too. It becomes a bug only when your code treats the answer as "this car is safe to drive" rather than "nothing here failed a check".
When emptiness is itself invalid, say so in the condition rather than expecting the method to guess:
let tyres: [Int] = []
let roadworthy = !tyres.isEmpty && tyres.allSatisfy { $0 > 0 }
print(roadworthy) // Program output:
// false allSatisfy Against filter and contains
Three methods take a very similar closure and answer three different questions. Picking the wrong one usually shows up as extra work rather than a compile error:
| Behaviour | allSatisfy | contains(where:) | filter |
|---|---|---|---|
| Question answered | Do all pass? | Does any pass? | Which ones pass? |
| Return type | Bool | Bool | Usually [Element]; Set and Dictionary preserve their kind |
| Stops early | On first failure | On first match | No, reads everything |
| Empty collection | true | false | Empty result |
Reach for allSatisfy when the next line is an if. Reach for filter when the next line needs the offending elements, usually to show the user which fields failed. Building the filtered collection just to compare its count against the original does the same job with more allocation.
Pitfalls and Debugging
Force-unwrapping Inside the Closure
A collection of optionals is where this method turns a validation into a crash. The forced unwrap runs before the comparison, so the nil traps:
let readings: [Double?] = [25.3, nil, 30.1]
let bad = readings.allSatisfy { $0! > 20 } // Typical Swift trap message (source prefix omitted):
// Fatal error: Unexpectedly found nil while unwrapping an Optional value Decide what nil means and encode that decision. If a missing reading is a failure, compare against the optional directly. If it should be skipped, drop the missing values first:
let strict = readings.allSatisfy { reading in
guard let reading else { return false }
return reading > 20
}
let lenient = readings.compactMap { $0 }.allSatisfy { $0 > 20 }
print(strict, lenient) // Program output:
// false true Side Effects That Stop Early
Short-circuiting is a feature until you put a print or a log call inside the closure. The output stops at the first failure, which reads like the collection was truncated:
let numbers = [2, 4, 5, 6]
_ = numbers.allSatisfy {
print("Checking \($0)")
return $0 % 2 == 0
} // Program output:
// Checking 2
// Checking 4
// Checking 5 The 6 was never examined. Use a for loop when the point of the pass is the side effect, and keep this method for the question it answers.
The Dictionary Element Is a Pair
Iterating a dictionary hands the closure a key-value tuple, so a comparison written for a plain value fails to compile:
let fields = ["email": "a@b.com", "username": ""]
let filled = fields.allSatisfy { !$0.value.isEmpty }
print(filled) // Program output:
// false Name the half you mean, either $0.key or $0.value. Writing { !$0.isEmpty } here produces a type error about the tuple, which is the compiler pointing at the right line for the wrong-sounding reason.
Frequently Asked Questions
Does allSatisfy check every element?
Only until one fails. It stops at the first element that returns false and hands back false immediately. When every element passes it does read the whole collection, because that is the only way to know.
What is the opposite of allSatisfy?
There is no allFail method. Use contains(where:) for whether any element matches, and negate it for whether none do. Writing !numbers.contains { $0 < 0 } reads as no element is negative.
Can the closure throw an error?
Yes. The method is marked rethrows, so a throwing closure makes the call throwing and you write try collection.allSatisfy { ... }. A non-throwing closure leaves the call non-throwing, with no try needed.
Does allSatisfy work on a dictionary?
Yes, because Dictionary is a Sequence. Each element is a key-value pair rather than a single value, so the closure reads $0.key or $0.value. Comparing $0 directly against a number will not compile.
Is allSatisfy faster than a for loop?
It is not meant to be faster. A loop with an early break does the same asymptotic work and short-circuits the same way, so benchmark if speed actually matters. The gain is that the intent is stated in one line, so a reader does not have to reconstruct it from a flag variable.
Why is it allSatisfy and not all?
Swift names methods after what they do to their argument, and this one asks whether all elements satisfy a predicate. The trailing underscore-colon form, allSatisfy(_:), is how the standard library writes a single unlabelled parameter.
Self-Check
- What does
allSatisfyreturn for an empty collection, and why? - Given
["Alice", "Anna", "Andrew"], what doesallSatisfy { $0.hasPrefix("A") }return? - Which method would you use to get back the elements that failed?
- What happens when the closure force-unwraps an optional that is
nil? - Why can a
printinside the closure appear to skip elements?
Answers
true. No element fails, because there are no elements. Add a!collection.isEmptycheck when emptiness should be a failure.true. All three names start with a capital A, so every call to the predicate answerstrue.filter. Invert the predicate to collect the failures, for examplefields.filter { $0.value.isEmpty }.- The program traps. The unwrap runs before the comparison, so it is a runtime crash rather than a
falseresult. - Short-circuiting. The method stops at the first failure, so nothing after that element is ever passed to the closure.
Related
- Sets in Swift - the other collection this method is most used on.
- Understanding typealias in Swift - name the closure type once when a predicate is reused.
- Swift - the language hub and its learning path.
Sources
-
[1]
allSatisfy(_:)(developer.apple.com)
-
[2]
Sequence(developer.apple.com)
Read Next
A Swift Set stores unique values with no order and answers membership questions in constant time on average. How to create one, run set algebra, make your own types storable, and decide between Set and Array.
The typealias keyword gives an existing type a second name. What it does to closures, tuples, dictionaries, and generics, what it deliberately does not do, and the errors it produces.
A practical Swift guide to optionals, value types, closures, async/await, SwiftUI state, and reviewing AI-assisted Apple platform code.