# Swift first and last: Accessing Collection Boundary Elements

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

Swift collections often need quick access to the item at the beginning or end of their contents. The `first` and `last` properties give you a safe way to read those boundary elements from arrays, strings, slices, sets, and other collections. In this article, you will learn how they work, why they return optionals, how to use them correctly, and what mistakes beginners commonly make.

> **Quick answer:** In Swift, `first` returns the first element in a collection and `last` returns the last element. Both return an optional value because the collection might be empty, so you usually handle them with `if let`, nil coalescing, or optional chaining.

> **Difficulty:** Beginner
>
> **Helpful to know first:** You will understand this better if you already know basic Swift syntax, optionals, and how collections like `Array` and `String` store values.

## 1. What Is first and last?

`first` and `last` are read-only collection properties in Swift that let you safely access the element at the start or end of a collection.

- `first` gives you the first element if one exists.
- `last` gives you the last element if one exists.
- Both return optionals because an empty collection has no boundary element to return.
- They work with many standard library collection types, including `Array`, `String`, `ArraySlice`, and `Set`.
- They are safer than manually indexing into a collection when emptiness is possible.

For many beginners, the most important idea is that these properties do not crash just because a collection is empty. Instead, Swift gives you `nil`, which forces you to handle the missing value explicitly.

> A useful comparison is `first` and `last` versus indexed access like `numbers[0]`. Indexed access expects a valid index and can crash if the collection is empty. `first` and `last` are designed for safe boundary access.

## 2. Why first and last Matters

These properties matter because reading the beginning or end of a collection is extremely common in real programs.

You might use them to:

- Check the first character of user input.
- Read the latest item from a list of messages.
- Inspect the first command-line argument after validation.
- Get the opening or closing value in a sequence of readings.
- Display a preview using only the start or end of stored data.

They also make code easier to read. Compare “get the first item if it exists” with manually computing indices and checking emptiness first. The property name communicates your intention immediately.

Use `first` or `last` when you want to read a boundary element safely. Do not use them when you need to remove elements, mutate the collection, or access a specific position in the middle.

## 3. Basic Syntax

### Reading the first element

Here is the simplest use of `first` with an array. Notice that the result is optional.

```swift
let numbers = [10, 20, 30]
let start = numbers.first

print(start as Any)
```

Output (tested with Swift 6.4):

```text
Optional(10)
```

This reads the first element of the array. The printed result is an optional value, because the array could have been empty.

### Reading the last element

`last` works the same way for the end of the collection.

```swift
let numbers = [10, 20, 30]
let end = numbers.last

print(end as Any)
```

Output (tested with Swift 6.4):

```text
Optional(30)
```

This safely reads the last element and returns an optional `Int`.

### Handling the optional result

In real code, you usually unwrap the result before using it.

```swift
let numbers = [10, 20, 30]

if let firstNumber = numbers.first {
    print("First number: \(firstNumber)")
}

if let lastNumber = numbers.last {
    print("Last number: \(lastNumber)")
}
```

Output (tested with Swift 6.4):

```text
First number: 10
Last number: 30
```

This is the core pattern you will use most often: read the optional, unwrap it safely, then work with the value.

## 4. Step-by-Step Examples

### Example 1: Getting the first item in an array

This example shows the most common case: reading the first value from an array of strings.

```swift
let fruits = ["Apple", "Banana", "Cherry"]

if let firstFruit = fruits.first {
    print("First fruit: \(firstFruit)")
}
```

Output (tested with Swift 6.4):

```text
First fruit: Apple
```

The array is not empty, so `first` contains `"Apple"`. This is a simple and safe way to read the first item.

### Example 2: Getting the last item in an array

You can do the same thing with the final item in a collection.

```swift
let scores = [88, 91, 95]

if let highestRecordedScore = scores.last {
    print("Last recorded score: \(highestRecordedScore)")
}
```

Output (tested with Swift 6.4):

```text
Last recorded score: 95
```

This returns the last stored score, not necessarily the highest numeric score. That is an important distinction: `last` means final element in collection order, not maximum value.

### Example 3: Working with an empty collection

This example shows why the result is optional. An empty array has no first or last element.

```swift
let emptyNames: [String] = []

print(emptyNames.first as Any)
print(emptyNames.last as Any)
```

Output (tested with Swift 6.4):

```text
nil
nil
```

Both results are `nil`. This is exactly why Swift makes you deal with the optional safely.

### Example 4: Using nil coalescing for a fallback value

If you want a default when the collection is empty, nil coalescing is often convenient.

```swift
let tasks: [String] = []

let firstTask = tasks.first ?? "No tasks"
let lastTask = tasks.last ?? "No tasks"

print(firstTask)
print(lastTask)
```

Output (tested with Swift 6.4):

```text
No tasks
No tasks
```

This pattern is useful when your program should continue with a sensible default value instead of branching with `if let`.

### Example 5: Using first and last with a String

Strings in Swift are collections of characters, so they also support `first` and `last`.

```swift
let word = "Swift"

if let firstCharacter = word.first,
   let lastCharacter = word.last {
    print("First: \(firstCharacter), Last: \(lastCharacter)")
}
```

Output (tested with Swift 6.4):

```text
First: S, Last: t
```

This reads the first and last `Character` values in the string. For strings, this is often much safer than trying to use integer indexing.

## 5. Practical Use Cases

- Reading the first item in a queue-like array before deciding what to process next.
- Showing the last message in a chat history preview.
- Checking the first character of user input to validate a format.
- Looking at the last saved value in a history of measurements or events.
- Reading the first error in a list of validation failures.
- Displaying the first image or last image in a gallery model.
- Using `first` on a filtered collection to get the earliest matching result.

## 6. Common Mistakes

### Mistake 1: Force-unwrapping first or last without checking

Because `first` and `last` return optionals, force-unwrapping them is dangerous if the collection may be empty.

**Problem:** This code crashes at runtime when the array has no elements, because `nil` is force-unwrapped.

```swift
let numbers: [Int] = []
print(numbers.first!)
```

**Fix:** Use optional binding or a fallback value so your code handles empty collections safely.

```swift
let numbers: [Int] = []

if let firstNumber = numbers.first {
    print(firstNumber)
} else {
    print("No numbers available")
}
```

Output (tested with Swift 6.4):

```text
No numbers available
```

The corrected version works because it explicitly handles the empty-array case instead of assuming a value exists.

### Mistake 2: Treating last as the maximum value

Some beginners assume `last` means the largest item. It does not. It means the final element according to the collection's order.

**Problem:** This code incorrectly assumes the last element is the highest score, which is only true if the array is already sorted in the needed order.

```swift
let scores = [95, 72, 88]
if let bestScore = scores.last {
    print("Best score: \(bestScore)")
}
```

Output (tested with Swift 6.4):

```text
Best score: 88
```

**Fix:** Use `max()` when you want the largest value, and use `last` only when you want the final stored element.

```swift
let scores = [95, 72, 88]

if let bestScore = scores.max() {
    print("Best score: \(bestScore)")
}
```

Output (tested with Swift 6.4):

```text
Best score: 95
```

The corrected version works because `max()` searches for the largest value instead of simply reading the final position.

### Mistake 3: Using indexed access when first is safer

Direct indexing can be fine when you are certain the collection has elements, but it is less safe for uncertain input.

**Problem:** This code crashes with an index out of range error if the array is empty.

```swift
let items: [String] = []
print(items[0])
```

**Fix:** Use `first` when you want the first element but the collection might be empty.

```swift
let items: [String] = []

if let firstItem = items.first {
    print(firstItem)
} else {
    print("The list is empty")
}
```

Output (tested with Swift 6.4):

```text
The list is empty
```

The corrected version works because `first` returns `nil` instead of causing an out-of-range crash.

### Mistake 4: Confusing first with removeFirst()

`first` only reads a value. It does not modify the collection. If you want to remove the first element, you need a mutating method such as `removeFirst()`.

**Problem:** This code reads the first value but leaves the array unchanged, which may break queue-like logic.

```swift
var queue = ["A", "B", "C"]

if let nextItem = queue.first {
    print("Processing \(nextItem)")
}

print(queue)
```

Output (tested with Swift 6.4):

```text
Processing A
["A", "B", "C"]
```

**Fix:** Use `removeFirst()` when you need to consume the element and update the collection.

```swift
var queue = ["A", "B", "C"]

if !queue.isEmpty {
    let nextItem = queue.removeFirst()
    print("Processing \(nextItem)")
}

print(queue)
```

Output (tested with Swift 6.4):

```text
Processing A
["B", "C"]
```

The corrected version works because `removeFirst()` both returns and removes the first element.

## 7. Best Practices

### Use optional binding when emptiness is normal

If an empty collection is a valid situation, optional binding keeps your code clear and safe.

```swift
let messages: [String] = []

if let latestMessage = messages.last {
    print("Latest: \(latestMessage)")
} else {
    print("No messages yet")
}
```

Output (tested with Swift 6.4):

```text
No messages yet
```

This approach is better than force-unwrapping because it makes the missing-data case explicit.

### Use nil coalescing when a default value makes sense

Sometimes you do not need separate branching. A fallback is enough.

```swift
let tags: [String] = []
let displayTag = tags.first ?? "untagged"

print(displayTag)
```

Output (tested with Swift 6.4):

```text
untagged
```

This is a good fit when you always want a usable value for display or simple logic.

### Choose first and last for intent, not cleverness

If you want the boundary element, say so directly with `first` or `last` instead of computing indices manually.

```swift
let colors = ["Red", "Green", "Blue"]

// Preferred
let startColor = colors.first
let endColor = colors.last
```

This makes the code easier to read and reduces the chance of indexing mistakes.

### Know when you need reading versus mutation

Use `first` and `last` for inspection only. Use mutating methods such as `removeFirst()` or `removeLast()` when the collection itself should change.

```swift
var history = ["v1", "v2", "v3"]

let currentPreview = history.last
let removedVersion = history.removeLast()

print(currentPreview as Any)
print(removedVersion)
```

Output (tested with Swift 6.4):

```text
Optional("v3")
v3
```

The distinction matters because one operation reads and the other changes program state.

## 8. Limitations and Edge Cases

- `first` and `last` return optionals, so you must handle `nil` for empty collections.
- For unordered collections such as `Set`, the meaning of “first” or “last” is about the collection's iteration order, not a sorted or predictable order. Do not assume a specific element.
- With `String`, the return type is `Character?`, not `String?`. Convert if you need a string value.
- `last` does not mean maximum, latest by date, or greatest by custom rule unless the collection is already ordered that way.
- `first` and `last` do not remove elements. If your code seems “not working” because the collection still contains the item, you likely needed `removeFirst()` or `removeLast()`.
- If you chain methods before using `first`, remember that the result type may change. For example, filtering an array and then taking `first` still returns an optional element.

## 9. Practical Mini Project

This small program analyzes a list of usernames. It prints the first and last username when available, and handles an empty list safely.

```swift
func printUserSummary(users: [String]) {
    print("User count: \(users.count)")

    if let firstUser = users.first {
        print("First user: \(firstUser)")
    } else {
        print("First user: none")
    }

    if let lastUser = users.last {
        print("Last user: \(lastUser)")
    } else {
        print("Last user: none")
    }
}

let activeUsers = ["Ava", "Noah", "Mia"]
let emptyUsers: [String] = []

printUserSummary(users: activeUsers)
print("---")
printUserSummary(users: emptyUsers)
```

Output (tested with Swift 6.4):

```text
User count: 3
First user: Ava
Last user: Mia
---
User count: 0
First user: none
Last user: none
```

This example is small, but it shows a realistic pattern: boundary access plus safe optional handling. The same approach works in larger applications whenever a collection might be empty.

## 10. Key Points

- `first` returns the first element of a collection as an optional.
- `last` returns the last element of a collection as an optional.
- They are safer than direct indexing when the collection may be empty.
- Use `if let` or `??` to handle missing values.
- `last` means final in collection order, not largest value.
- `first` and `last` read values but do not remove them.
- They work with many Swift collections, including arrays and strings.

## 11. Practice Exercise

Try this exercise to make sure you can use both properties correctly.

- Create an array of three city names.
- Print the first city using safe optional binding.
- Print the last city using safe optional binding.
- Create an empty array of city names.
- Print a fallback message for the first and last values of the empty array using nil coalescing.

**Expected output:** The program should print the first and last city from the non-empty array, then print fallback text for the empty array.

**Hint:** Remember that both properties return optionals, even when the array usually has values.

```swift
let cities = ["London", "Paris", "Tokyo"]

if let firstCity = cities.first {
    print("First city: \(firstCity)")
}

if let lastCity = cities.last {
    print("Last city: \(lastCity)")
}

let emptyCities: [String] = []

let emptyFirst = emptyCities.first ?? "No first city"
let emptyLast = emptyCities.last ?? "No last city"

print(emptyFirst)
print(emptyLast)
```

Output (tested with Swift 6.4):

```text
First city: London
Last city: Tokyo
No first city
No last city
```

## 12. Final Summary

Swift's `first` and `last` properties are small features, but they solve a very common problem: safely reading the boundary elements of a collection. They make your code more readable, reduce indexing errors, and work naturally with Swift's optional system.

The key thing to remember is that both properties return optionals. That design protects you from empty collections and encourages safer code through optional binding or fallback values. If you are comfortable with these properties, a good next step is to learn related collection operations such as `isEmpty`, `removeFirst()`, `removeLast()`, and methods like `min()` and `max()`.
