Swift contains and allSatisfy: Check Collection Values

Swift collections often need simple yes-or-no checks: does this collection include a value, and do all elements match a rule? That is exactly what contains and allSatisfy are for. In this article, you will learn what each method does, how their closure-based forms work, when to use one instead of the other, and how to avoid common mistakes when checking arrays, sets, and other sequences.

Quick answer: Use contains when you want to know whether at least one element matches a value or condition. Use allSatisfy when you want to know whether every element in the collection matches a condition.

Difficulty: Beginner

Helpful to know first: You will understand this better if you know basic Swift syntax, how arrays store values, and how simple closures return Bool values.

1. What Is contains and allSatisfy?

contains and allSatisfy are standard library methods available on Swift sequences such as arrays, sets, ranges, and many other collection-like types.

These methods solve a very common problem: checking a collection without writing a full loop yourself. Instead of manually iterating and tracking a flag variable, you can express your intent directly.

These two methods are also naturally compared because they sound similar but answer different questions. contains looks for any match. allSatisfy checks whether every element passes.

2. Why contains and allSatisfy Matters

These methods make code easier to read because they describe the exact question you are asking.

For example, in real projects you may need to:

Without these methods, you would often write a loop, compare each element, and stop manually when the answer is known. That works, but it is more verbose and easier to get wrong. Using contains or allSatisfy makes the code shorter and clearer.

Both methods can stop early. For example, contains can return as soon as it finds a match, and allSatisfy can return as soon as it finds an element that fails the rule.

3. Basic Syntax or Core Idea

Using contains with a value

If the collection elements are comparable for equality, you can ask whether a collection contains a specific value.

let numbers = [10, 20, 30]
let hasTwenty = numbers.contains(20)

print(hasTwenty) // true

This form is simple: Swift checks whether any element equals 20.

Using contains with a closure

Use the closure form when you want to match a condition instead of one exact value.

let numbers = [10, 20, 30]
let hasLargeValue = numbers.contains { number in
number > 25
}

print(hasLargeValue) // true

The closure returns true for a matching element. If any element returns true, then contains returns true.

Using allSatisfy with a closure

allSatisfy checks whether every element passes the condition.

let scores = [80, 92, 88]
let allPassed = scores.allSatisfy { score in
score >= 50
}

print(allPassed) // true

If even one score fails the condition, allSatisfy returns false.

The core difference

Think of them like this:

4. Step-by-Step Examples

Example 1: Check for a specific string

This example uses contains to check whether a list of names includes a specific value.

let names = ["Ava", "Noah", "Mia"]
let hasMia = names.contains("Mia")

print(hasMia) // true

This is the best form when you know the exact value you want to find.

Example 2: Check whether any number is even

Here, an exact value is not enough. We want to test a rule, so the closure form of contains is the right choice.

let values = [3, 7, 10, 13]
let hasEven = values.contains { value in
value % 2 == 0
}

print(hasEven) // true

The method returns true because 10 matches the condition.

Example 3: Check whether all strings are non-empty

allSatisfy is useful when every element must meet a rule.

let usernames = ["alice", "bob", "charlie"]
let allHaveText = usernames.allSatisfy { !$0.isEmpty }

print(allHaveText) // true

This reads cleanly: all usernames satisfy the rule of being non-empty.

Example 4: Check object properties with contains

These methods are especially useful with custom types. In this example, we check whether any task is overdue.

struct Task {
let title: String
let isOverdue: Bool
}

let tasks = [
Task(title: "Send invoice", isOverdue: false),
Task(title: "Reply to email", isOverdue: true)
]

let hasOverdueTask = tasks.contains { task in
task.isOverdue
}

print(hasOverdueTask) // true

This approach avoids writing a manual loop and clearly expresses the intent.

5. Practical Use Cases

6. Common Mistakes

Mistake 1: Using contains when you really mean allSatisfy

A common beginner mistake is choosing contains for a rule that every element must satisfy.

Problem: This code only checks whether at least one number is positive, not whether all numbers are positive. The result can be true even when some elements fail the rule.

let numbers = [5, -2, 8]
let allPositive = numbers.contains { $0 > 0 }

print(allPositive) // true, but misleading

Fix: Use allSatisfy when the condition must hold for every element.

let numbers = [5, -2, 8]
let allPositive = numbers.allSatisfy { $0 > 0 }

print(allPositive) // false

The corrected version works because allSatisfy checks every element instead of stopping at the first success.

Mistake 2: Trying to pass a value to allSatisfy

allSatisfy does not have the same direct-value form as contains. It expects a closure that returns Bool.

Problem: This code is not valid Swift because allSatisfy requires a predicate closure, not a single value to compare against.

let statuses = ["ready", "ready", "ready"]
let allReady = statuses.allSatisfy("ready")

Fix: Provide a closure that compares each element with the expected value.

let statuses = ["ready", "ready", "ready"]
let allReady = statuses.allSatisfy { $0 == "ready" }

print(allReady) // true

The corrected version works because the closure checks each element one at a time.

Mistake 3: Forgetting that empty collections affect allSatisfy

Many developers expect allSatisfy to return false for an empty collection, but that is not how it works.

Problem: An empty collection has no elements that fail the condition, so allSatisfy returns true. This can surprise you if you also need at least one element.

let scores: [Int] = []
let allPassed = scores.allSatisfy { $0 >= 50 }

print(allPassed) // true

Fix: If your rule requires a non-empty collection, combine allSatisfy with an emptiness check.

let scores: [Int] = []
let allPassed = !scores.isEmpty && scores.allSatisfy { $0 >= 50 }

print(allPassed) // false

The corrected version works because it checks both requirements: there must be elements, and they must all pass.

7. Best Practices

Practice 1: Use the simplest form of contains when checking one exact value

If you only need to find one exact value, prefer the direct-value form of contains. It is more readable than writing a closure for the same comparison.

// Less preferred
let roles = ["admin", "editor", "viewer"]
let hasAdmin = roles.contains { $0 == "admin" }

// Preferred
let betterHasAdmin = roles.contains("admin")

The preferred version is easier to scan because it directly communicates the search value.

Practice 2: Choose method names that reflect the question you are asking

Store the result in a variable whose name makes the logic obvious. This becomes especially useful in conditions and validation code.

let emails = ["[email protected]", "[email protected]"]
let allEmailsValid = emails.allSatisfy { $0.contains("@") }

if allEmailsValid {
print("Ready to submit")
}

A descriptive Boolean name helps the condition read like plain English.

Practice 3: Keep closure conditions focused and easy to read

If the condition is too complex, move the logic into a helper property or function. This keeps collection checks expressive instead of cluttered.

struct User {
let name: String
let age: Int

var isAdult: Bool {
age >= 18
}
}

let users = [
User(name: "Anna", age: 21),
User(name: "Ben", age: 19)
]

let allAdults = users.allSatisfy { $0.isAdult }

This version is cleaner than putting a long rule directly inside the closure.

8. Limitations and Edge Cases

9. Practical Mini Project

This mini project validates a list of orders. We want to know whether any order is urgent and whether all orders are ready to ship.

struct Order {
let id: Int
let isUrgent: Bool
let isPacked: Bool
}

let orders = [
Order(id: 101, isUrgent: false, isPacked: true),
Order(id: 102, isUrgent: true, isPacked: true),
Order(id: 103, isUrgent: false, isPacked: true)
]

let hasUrgentOrder = orders.contains { $0.isUrgent }
let allOrdersPacked = orders.allSatisfy { $0.isPacked }

print("Urgent order present:", hasUrgentOrder)
print("All orders packed:", allOrdersPacked)

This example shows both methods working together in a realistic validation scenario. contains answers whether at least one urgent order exists, while allSatisfy confirms whether every order is packed.

10. Key Points

11. Practice Exercise

Create a Swift program that works with an array of temperatures.

Expected output: Two printed Boolean results: one for whether any temperature is freezing, and one for whether all temperatures are under the limit.

Hint: Use closure expressions such as { $0 < 0 } and { $0 < 40 }.

let temperatures = [12, -3, 18, 25]

let hasFreezingTemperature = temperatures.contains { $0 < 0 }
let allBelowLimit = temperatures.allSatisfy { $0 < 40 }

print("Any below zero:", hasFreezingTemperature)
print("All below 40:", allBelowLimit)

12. Final Summary

contains and allSatisfy are small methods, but they solve very common collection-checking problems in a clear and expressive way. Use contains when you want to know whether any matching element exists, and use allSatisfy when every element must follow the same rule.

You also saw that the direct-value form of contains is ideal for exact matches, while closure-based checks are better for custom logic. Just be careful with empty collections and choose the method that matches your real question: “any?” or “all?” A good next step is to learn related collection methods such as first(where:), filter, and map so you can do more than just Boolean checks.