🔍 Why check for an element in a Swift array? And how to do it correctly in 2025?
\n\nImagine: you are writing a pizza ordering app. The user selected "Pepperoni", "Hawaiian", and "Margherita". Your code must ensure that "Pepperoni" is already in the cart to avoid adding a duplicate. Or you are working with a customer database and checking if an email is registered in the system. Checking for the presence of an element in an array is one of the most common operations in Swift development.
\n\nIt seems simple, right? But in 2025, when Swift is evolving rapidly and mobile app performance is critical, choosing the wrong method can cost you UI lag or extra hours of debugging. In this article, we will cover all the ways to check for an element in a Swift array: from the simple contains() to advanced closures and working with custom types. You will learn which method to choose for your task and why.
By the way, this question is one of the most popular on Stack Overflow (over 200,000 views). And we will give you a comprehensive, modern answer. Let's go! 🚀
\n\n📦 Arrays in Swift: A Basic Overview (for those in a hurry)
\n\nAn array (Array) is an ordered collection of elements of the same type. In Swift, arrays are type-safe, meaning you cannot accidentally add a string to an array of numbers. This is both a plus (fewer bugs) and a challenge (you need to strictly specify types).
let pizzaMenu: [String] = ["Margherita", "Pepperoni", "Hawaiian", "Four Cheese"]\nlet numbers: [Int] = [1, 2, 3, 4, 5]\n\n\nNow let's move to the main point — how to check if an element exists in an array?
\n\n🛠️ Top 5 Methods for Checking the Presence of an Element in a Swift Array
\n\n1. contains() — The King of Simplicity (Equatable)
\n\nThe most obvious and frequently used method. The contains(_:) method returns true if the element is found. It only works with types that conform to the Equatable protocol (which includes all basic types: String, Int, Double, etc.).
let pizzas = ["Margherita", "Pepperoni", "Hawaiian"]\nif pizzas.contains("Pepperoni") {\n print("This pizza exists!") // ✅ Will print this\n} else {\n print("Pizza not found")\n}\n\n\nPros: readable, concise, fast.
\nCons: does not work if you have a complex object (struct/class) without Equatable.
2. contains(where:) — For Complex Checks
\n\nIf you need to check not for an exact match, but for a condition (e.g., "is there a pizza more expensive than 500 rubles?"), use contains(where:). It takes a closure that returns a Bool.
struct Pizza {\n let name: String\n let price: Int\n}\n\nlet order: [Pizza] = [\n Pizza(name: "Margherita", price: 450),\n Pizza(name: "Pepperoni", price: 550),\n Pizza(name: "Hawaiian", price: 500)\n]\n\nlet hasExpensivePizza = order.contains { $0.price > 500 }\nprint("Is there an expensive pizza? \\(hasExpensivePizza)") // true\n\n\nPros: flexibility, works with any types.
\nCons: slightly slower than contains() (but the difference is negligible for 99% of cases).
3. firstIndex(of:) — When the Index Matters
\n\nSometimes you need not just to know if an element exists, but also to get its position. For example, to delete or replace it. The firstIndex(of:) method returns an optional Int?.
let pizzas = ["Margherita", "Pepperoni", "Hawaiian"]\nif let index = pizzas.firstIndex(of: "Pepperoni") {\n print("Pepperoni is at position \\(index)") // 1\n} else {\n print("Not found")\n}\n\n\nImportant: firstIndex also requires Equatable. If your type does not conform