Implementing SequenceType
Sometimes you have a struct/class that holds some kind of sequence and
you would like to iterate over it with for ... in .... In
Swift the struct/class has to conform to SequenceType to
enable this iteration.
Let’s say you have a simple struct to hold domains:
struct Domains {
let names: [String]
let tld: String
}To conform to SequenceType the
struct needs to implement the method:
func generate() -> Self.Generatorand the Generator is of type
GeneratorType. Ok, let’s start with the generator.
The protocol GeneratorType looks
like this:
protocol GeneratorType {
/// The type of element generated by `self`.
typealias Element
/// Advance to the next element and return it, or `nil` if no next
/// element exists.
mutating func next() -> Self.Element?
}So, the generator need to implement a method next() that returns
the next element until no element is left.
A simple generator for the Domains struct could look like this:
struct DomainsGenerator : GeneratorType {
var domains: Domains
var index = 0
init(domains: Domains) {
self.domains = domains
}
mutating func next() -> String? {
return index < domains.names.count ? "\(domains.names[index++]).\(domains.tld)" : nil
}
}The method is mutating because it changes the index property.
The Domains struct would then conform to SequenceType like
this:
func generate() -> DomainsGenerator {
return DomainsGenerator(domains: self)
}The complete example looks like this:
struct Domains {
let names: [String]
let tld: String
}
extension Domains : SequenceType {
func generate() -> DomainsGenerator {
return DomainsGenerator(domains: self)
}
struct DomainsGenerator : GeneratorType {
var domains: Domains
var index = 0
init(domains: Domains) {
self.domains = domains
}
mutating func next() -> String? {
return index < domains.names.count ? "(domains.names[index++]).(domains.tld)" : nil
}
}
}
let domains = Domains(names: ["swiftandpainless","duckduckgo","apple","github"], tld: "com")
for domain in domains {
print(domain)
}