First of all, let's take a look at some methods introduced to us in Apple's official documents
The first one is about the initialization method of AnyIterator. The official explanation is to create an iterator that wraps the given closure in its next () method. So the following example initializes AnyIterator for the next method
init(_body: @escaping () -> AnyIterator.Element?)
Then let's look at the example
var x = 7
let iterator: AnyIterator<Int> = AnyIterator {
defer { x += 1 }
return x < 15 ? x : nil
}
let a = Array(iterator)
// a == [7, 8, 9, 10, 11, 12, 13, 14]
So we can know to return the elements we want to return to the iterator until nil
Let's look at our AnySequence initialization method, which is called above
init<I>(_makeUnderlyingIterator: @escaping () -> I) where Element == I.Element, I : IteratorProtocol
Method 1: then we define an iterator that complies with both iterator protocol and Sequence protocol
struct MyIterator<Element>:IteratorProtocol, Sequence {
//closure
var base:()->Element?
init(_ body: @escaping () -> Element?)
{
//Closure saved
base = body
}
//WrittennextMethod
func next() -> Element?
{
return base()
}
}
In the outside world, we can create an iterator by ourselves. A call to the next method is equivalent to a call to the closure saved in the iterator, and our for in loop. As long as for in is an object that follows the Sequence protocol, it can use the for in loop to iterate. Its essence is to call the next() method
var x = 7
let iterator:MyIterator<Int> = MyIterator {
defer { x += 1 }
return x < 15 ? x : nil
}
print("\(iterator.next())")
print("\(iterator.next())")
for a in iterator {
print(a)
}
The output is as follows
Method 2: we can also wrap the iterator into the array and then traverse the output
for a in Array(iterator)
{
print(a)
}
Method 3: another implementation method of iterator, the MyIterator structure follows the Sequence protocol and implements the makeIterator() method
struct MyIterator<Element>:Sequence
{
public func makeIterator() -> AnyIterator<Int> {
var idx = 0
return AnyIterator {
if idx >= 5 {
return Optional<Int>.none
} else {
//Otherwise, the corresponding value is returned
idx += 1
return idx
}
}
}
}
On the outside, we can directly put the container that we have complied with the Sequence protocol into Array, and then call the for -in loop to traverse it.
let iterator = MyIterator<Int>()
for a in Array(iterator)
{
print(a)
}
for a in Array(iterator)
{
print(a)
}
}
Method 4: we can use the following method to output until nil
var idx = 1;
var base:()->Int? = {
defer {
idx += 1
}
return idx < 5 ? idx : nil
}
let sequenc = AnySequence{
AnyIterator {
base()
}
}
for a in sequenc {
print(a)
}
}