When you implement the SequenceType protocol you can iterate over the data in your object as follows:
for x in objectOfMyClass {
... process x
}
protocol SequenceType : _Sequence_Type {
typealias Generator : GeneratorType
func generate() -> Generator
}
It needs just one function that returns an object which implements the GeneratorType protocol. It can be tempting to return "self" as the generator. And that will indeed work, ... a little. It is however dangerous as you have no protection against multiple uses of the same generator, for example with nested loops or object access from multiple threads. A safer approach is to create a unique generator object on each call to the generate function. Still, even then, writing a safe generator can be a bit daunting as you need to think about mutations that could occur while you are iterating over your internal data.
The GeneratorType protocol is also very simple, you just have to implement one function:
protocol GeneratorType {
typealias Element
mutating func next() -> Element?
}
Here is an implementation that I think is relatively robust:
class MyDataClass {
var myData = "data"
}
class MyClass: SequenceType {
func values() -> Array<MyDataClass>? { return ... }
struct MyClassGenerator: GeneratorType {
typealias Element = MyDataClass
// The object for which the generator generates
let source: MyClass
// The objects already delivered through the generator
var sent: Array<MyDataClass> = []
init(source: MyClass) {
self.source = source
}
// The GeneratorType protocol
mutating func next() -> Element? {
// Only when the source has values to deliver
if var values = source.values() {
// Find a value that has not been sent already
OUTER: for i in values {
// Check if the value has not been sent already
for s in sent {
// If it was sent, then try the next value
if i === s { continue OUTER }
}
// Found a value that was not sent yet
// Remember that it will be sent
sent.append(i)
// Send it
return i
}
}
// Nothing left to send
return nil
}
}
typealias Generator = MyClassGenerator
func generate() -> Generator {
return MyClassGenerator(source: self)
}
}
This implementation keeps track of mutations that can occur in the source class and will respect these mutations on subsequent calls to "next()". Hence updates being made to a MyClass object will be respected. For example deleting MyDataClass objects that have been sent already will not upset the for loop, nor will removing MyDataClass objects that have not been sent yet result in "next()-ing" data that is not present anymore.
Happy coding ...
Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH
We don't get the world we wish for... we get the world we pay for.
Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH
We don't get the world we wish for... we get the world we pay for.
No comments:
Post a Comment