# A Beginner's Guide to Arrays in Swift

Source: https://devdocs10.com/articles/swift/swift-arrays  
By Murat Bo · Updated 2026-10-17 · DevDocs10 (https://devdocs10.com)

## 1. What Are Arrays in Swift?

An array in Swift is an ordered collection of items of the same type, stored in a sequence. Think of it like a numbered list where each item has a position (index), starting at 0. Arrays are great for storing and accessing data in a specific order, like a list of names, scores, or tasks.

### Key Points:

- Arrays are **type-safe**: all elements must be of the same type (e.g., all integers, all strings).
- Arrays are **ordered**: elements stay in the order you add them.
- Arrays are **indexed**: you access elements using their position (e.g., `array[0]` for the first item).
- Arrays are **flexible**: you can add, remove, or modify elements.

### Why Use Arrays?

Arrays are useful when you need to:

- Store a list of items in a specific order (e.g., a to-do list).
- Access items by their position.
- Iterate over items to perform actions (e.g., display a list in a UI).
- Work with collections that might change (e.g., adding or removing items).

### When to Use Arrays?

- Use arrays when order matters (unlike sets, which are unordered).
- Use arrays when you need to access elements by index.
- Use arrays for lists in SwiftUI, like displaying rows in a `List`.

## 2. Basics of Arrays

Let’s break down how to create, use, and modify arrays step by step.

### Step 1: Creating an Array

You can create an array in several ways:

#### Using Array Literal Syntax:

```swift

let numbers = [1, 2, 3, 4] // An array of integers
let names = ["Alice", "Bob", "Charlie"] // An array of strings
```

#### Using Array<Type> Syntax:

```swift

let numbers: Array<Int> = [1, 2, 3, 4] // Same as above
let emptyArray: [String] = [] // Empty array of strings
```

#### Using Array(repeating:count:):

```swift

let zeros = Array(repeating: 0, count: 5) // [0, 0, 0, 0, 0]
```

> Note: The `let` keyword makes the array immutable (unchangeable). Use `var` if you need to modify the array later.

### Step 2: Accessing Elements

Arrays use zero-based indexing, so the first element is at index 0.

```swift

let fruits = ["Apple", "Banana", "Orange"]
print(fruits[0]) // Output: Apple
print(fruits[2]) // Output: Orange
```

Output (tested with Swift 6.4):

```text
Apple
Orange
```

**Caution:**Accessing an index that doesn’t exist (e.g., `fruits[3]`) causes a runtime crash. Always check the array’s size using `count`.

### Step 3: Modifying Arrays

You can modify arrays (if declared with `var`) by adding, removing, or changing elements.

#### Adding Elements:

```swift

var animals = ["Cat", "Dog"]
animals.append("Bird") // Adds to the end: ["Cat", "Dog", "Bird"]
animals += ["Fish", "Hamster"] // Adds multiple: ["Cat", "Dog", "Bird", "Fish", "Hamster"]
animals.insert("Snake", at: 1) // Inserts at index 1: ["Cat", "Snake", "Dog", "Bird", "Fish", "Hamster"]
```

#### Removing Elements:

```swift

var numbers = [1, 2, 3, 4]
numbers.remove(at: 1) // Removes 2: [1, 3, 4]
numbers.removeLast() // Removes 4: [1, 3]
numbers.removeAll() // Empties the array: []
```

#### Updating Elements:

```swift

var scores = [90, 85, 88]
scores[1] = 95 // Updates index 1: [90, 95, 88]
```

### Step 4: Checking Array Properties

#### Count: Number of elements.

```swift

let fruits = ["Apple", "Banana"]
print(fruits.count) // Output: 2
```

Output (tested with Swift 6.4):

```text
2
```

#### isEmpty: Checks if the array is empty.

```swift

print(fruits.isEmpty) // Output: false
print([].isEmpty) // Output: true
```

## 3. Examples for Different Scenarios

Let’s explore arrays in various contexts with beginner-friendly examples.

### Example 1: Array of Numbers

Processing a list of numbers, like calculating their sum.

```swift

let numbers = [10, 20, 30, 40]
var sum = 0
numbers.forEach { number in
    sum += number
}
print("Sum: \(sum)") // Output: Sum: 100
```

Output (tested with Swift 6.4):

```text
Sum: 100
```

### Example 2: Array of Strings

Filtering names that start with a specific letter.

```swift

let names = ["Alice", "Bob", "Anna", "Charlie"]
let aNames = names.filter { $0.hasPrefix("A") }
print(aNames) // Output: ["Alice", "Anna"]
```

Output (tested with Swift 6.4):

```text
["Alice", "Anna"]
```

### Example 3: Array with Dictionaries

Arrays can hold dictionaries for structured data.

```swift

let students = [
    ["name": "Alice", "grade": "A"],
    ["name": "Bob", "grade": "B"]
]
students.forEach { student in
    print(" \(student["name"]!): \(student["grade"]!)")
}
// Output:
// Alice: A
// Bob: B
```

Output (tested with Swift 6.4):

```text
 Alice: A
 Bob: B
```

**Note:**Use optional binding (`if let`) instead of force-unwrapping (`!`) in real apps to avoid crashes if keys are missing.

### Example 4: Array with Custom Structs

Arrays often store custom types, like structs.

```swift

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

let tasks = [
    Task(title: "Buy milk", isCompleted: false),
    Task(title: "Read book", isCompleted: true)
]
tasks.forEach { task in
    print(" \(task.title): \(task.isCompleted ? "Done" : "Pending")")
}
// Output:
// Buy milk: Pending
// Read book: Done
```

Output (tested with Swift 6.4):

```text
 Buy milk: Pending
 Read book: Done
```

### Example 5: SwiftUI with Arrays

Arrays are commonly used in SwiftUI to display lists of data. Here’s a simple to-do list app.

```swift

import SwiftUI

struct ContentView: View {
    let tasks = ["Buy milk", "Read book", "Call mom"]
    
    var body: some View {
        List {
            ForEach(tasks, id: \.self) { task in
                Text(task)
                    .padding()
            }
        }
    }
}
```

**Explanation:**

- `ForEach(tasks, id: \.self)` iterates over the `tasks` array, using each string as its own identifier (since `String` is `Hashable`).
- Each `task` is displayed as a Text view in a List.

### Example 6: SwiftUI with Range-Based ForEach

If you need indices (e.g., for numbering), use a range-based `ForEach`.

```swift

import SwiftUI

struct ContentView: View {
    let tasks = ["Buy milk", "Read book", "Call mom"]
    
    var body: some View {
        List {
            ForEach(0..<tasks.count, id: \.self) { index in
                Text("\(index + 1). \(tasks[index])")
                    .padding()
            }
        }
    }
}
```

**Output:** Displays “1. Buy milk”, “2. Read book”, “3. Call mom” in a list.

### Example 7: Dynamic Arrays in SwiftUI

For arrays that change (e.g., adding tasks), use @State and Identifiable types.

```swift

import SwiftUI

struct Task: Identifiable {
    let id = UUID()
    let title: String
}

struct ContentView: View {
    @State var tasks = [
        Task(title: "Buy milk"),
        Task(title: "Read book")
    ]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(tasks) { task in
                    Text(task.title)
                }
                .onDelete(perform: { indexSet in
                    tasks.remove(atOffsets: indexSet)
                })
            }
            .toolbar {
                Button("Add Task") {
                    tasks.append(Task(title: "Task \(tasks.count + 1)"))
                }
            }
        }
    }
}
```

**Explanation:**

- `Task` conforms to `Identifiable`, so `ForEach(tasks)` doesn’t need an `id` parameter.
- `@State` makes the array dynamic, updating the UI when tasks are added or removed.
- `.onDelete` allows swiping to delete tasks.

## 4. Common Use Cases

- **Storing Lists:** Keep track of items like to-dos, scores, or inventory.
- **Iterating:** Loop through items to process or display them (e.g., using `forEach`, `map`, or `filter`).
- **SwiftUI Lists:** Display dynamic lists in a UI, like a table of contacts.
- **Data Processing:** Transform or analyze data, like sorting or filtering.
- **Combining with Other Types:** Store dictionaries or structs for complex data (e.g., a list of user profiles).

## 5. When and Why to Use Arrays

### When to Use:

- When you need an ordered collection (e.g., a playlist where song order matters).
- When you need to access elements by index (e.g., `array[2]`).
- When displaying lists in SwiftUI (e.g., a `List` of items).
- When the collection might change (e.g., adding/removing items).

### Why Use Arrays:

- **Simplicity:** Easy to create and use for ordered data.
- **Flexibility:** Supports adding, removing, and modifying elements.
- **SwiftUI Integration:** Perfect for dynamic UI lists with `ForEach`.
- **Rich Methods:** Built-in methods like `map`, `filter`, and `sorted` make data manipulation easy.

### When Not to Use:

- Use a `Set` for unordered, unique items.
- Use a `Dictionary` for key-value pairs.
- Use a custom struct for more complex data relationships.

## 6. Best Practices

### Use Type Annotations for Clarity:

```swift

var names: [String] = [] // Clear that this is an array of strings
```

### Check Bounds to Avoid Crashes:

```swift

let array = [1, 2, 3]
if array.indices.contains(2) {
    print(array[2]) // Safe access
}
```

Output (tested with Swift 6.4):

```text
3
```

### Use Identifiable in SwiftUI:

For SwiftUI lists, make custom types conform to `Identifiable` to simplify `ForEach`:

```swift

struct Item: Identifiable {
    let id = UUID()
    let name: String
}
```

### Prefer Collection-Based ForEach in SwiftUI:

Use `ForEach(array, id: \.self)` or `Identifiable` types over `ForEach(0..<count)` for dynamic data to avoid index issues.

### Use Functional Methods:

Leverage `map`, `filter`, and `reduce` for clean, functional code:

```swift

let numbers = [1, 2, 3]
let doubled = numbers.map { $0 * 2 } // [2, 4, 6]
```

### Keep Arrays Immutable When Possible:

Use `let` for arrays that won’t change to prevent accidental modifications.

## 7. Limitations

- **Index Out-of-Range Crashes:** Accessing an invalid index (e.g., `array[10]` when `array.count` is 5) causes a crash.
- **Type Safety:** All elements must be the same type. Mixing types (e.g., `[1, "hello"]`) requires `Any` or a custom enum, which is less common.
- **Performance:** Large arrays with frequent insertions/removals at the start can be slow (use other structures like linked lists for such cases).
- **SwiftUI Range-Based ForEach:** Using `ForEach(0..<count)` can cause issues if the array changes size, as indices may shift.

## 8. Tips to Avoid Mistakes

### Avoid Index Out-of-Range Errors:

Check `array.count` or use `indices`:

```swift

let array = [1, 2, 3]
if !array.isEmpty {
    print(array.last!) // Safe if checked
}
```

Output (tested with Swift 6.4):

```text
3
```

### Use Optional Binding in SwiftUI:

When accessing array elements, avoid force-unwrapping:

```swift

if let first = array.first {
    print(first)
}
```

### Test Dynamic Data in SwiftUI:

When using `@State` arrays, test adding/removing items to ensure UI updates correctly.

### Avoid Range-Based ForEach for Dynamic Data:

Use `Identifiable` types or `id: \.self` for arrays that change:

```swift

ForEach(tasks, id: \.self) { task in ... }
```

### Use Descriptive Variable Names:

Name arrays clearly (e.g., `tasks` instead of `array`) to improve code readability.

## 9. Practice Exercise

Try this to solidify your understanding:

- Create an array of 5 favorite foods.
- Print each food with its position (e.g., “1. Pizza”).
- Add a new food to the end and remove the second food.
- Create a SwiftUI view to display the foods in a list, with a button to add a new food.

### Solution:

```swift

// Standard Swift
var foods = ["Pizza", "Sushi", "Burger", "Pasta", "Salad"]
foods.enumerated().forEach { (index, food) in
    print("\(index + 1). \(food)")
}
foods.append("Taco") // Add Taco
foods.remove(at: 1) // Remove Sushi
print(foods) // Output: ["Pizza", "Burger", "Pasta", "Salad", "Taco"]

// SwiftUI
import SwiftUI

struct ContentView: View {
    @State var foods = ["Pizza", "Sushi", "Burger", "Pasta", "Salad"]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(foods, id: \.self) { food in
                    Text(food)
                }
                .onDelete(perform: { indexSet in
                    foods.remove(atOffsets: indexSet)
                })
            }
            .toolbar {
                Button("Add Food") {
                    foods.append("Taco \(foods.count + 1)")
                }
            }
        }
    }
}
```
