NEW! Master Swift design patterns with my latest book! >>

How to make a custom sequence

Paul Hudson       @twostraws

When you use a for-in loop, Swift maps that code to a while loop that generates an iterator for your data. Swift then calls next() on that iterator repeatedly until it gets back nil to signal that the loop has ended.

This functionality is all handled through two protocols: Sequence describes something that can be looped over, and IteratorProtocol describes something that iterates over a sequence. If you combine them both into a single type, all you need to do is implement a next() method returning whatever value comes next in your sequence.

Let’s walk through a simple sequence that counts doubles up from 1, so it will count 1, 2, 4, 8, 16, 32, 64, 128, 256, and so on until we run out of integers that can be stored in Int.

In code this means creating a new DoubleGenerator struct that conforms to both Sequence and IteratorProtocol. Because this type conforms to both protocols, we only need to implement one method: next(). This should double the current number then return it, however we need to do that doubling inside a defer block so that we only double after we’ve returned.

Here’s the code:

struct DoubleGenerator: Sequence, IteratorProtocol {
    var current = 1

    mutating func next() -> Int? {
        defer {
            current *= 2
        }

        return current
    }
}

As that’s an infinite sequence you should be careful using it. For example, this code increments a counter each time its loop goes around and exits the loop when the counter reaches 10.

var i = 0

let numbers = DoubleGenerator()
for number in numbers {
    i += 1
    if i == 10 { break }

    print(number)
}

That will print doubles of 1 through to 256.

If you want your iterator and sequences to be different types, you’ll need to add a makeIterator() method to your sequence.

Available from iOS 8.0 – learn more in my book Swift Design Patterns

Did this solution work for you? Please pass it on!

Other people are reading…

About the Swift Knowledge Base

This is part of the Swift Knowledge Base, a free, searchable collection of solutions for common iOS questions.

Want to build macOS apps?

Hacking with macOS delivers 18 awesome projects that teach you macOS development in no time – take control of your desktop today!

MASTER SWIFT NOW
Buy Practical iOS 12 Buy Pro Swift Buy Swift Design Patterns Buy Practical iOS 11 Buy Swift Coding Challenges Buy Server-Side Swift (Vapor Edition) Buy Server-Side Swift (Kitura Edition) Buy Hacking with macOS Buy Advanced iOS Volume One Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with Swift Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let me know!

Click here to visit the Hacking with Swift store >>