I really liked Sulthan's answer (in Anonymous class in swift) which describes building an object which conforms to a protocol but whose class is hidden inside a closure. This would be nice for building singletons and not polluting the name-space with classes like Recorder1, Recorder2...
However, when I try to do anything useful with it, I fail because the closure will not close over the outer class' instance members inside the inner class.
protocol EventListener {
func handleEvent(event: Int) -> ()
}
class Recorder {
static var events = [Int]() // static is forced
var listener: EventListener = {
class R : EventListener {
func handleEvent(event: Int) {
events.append(event)
print("Recorded: \(event)")
}
}//
return R()
}()
}// Recorder
class Distributor {
var listeners = [EventListener]()
func register(listener: EventListener){
listeners.append(listener)
}
func distribute(event: Int){
for listener in listeners {
listener.handleEvent(event)
}
}
}
var d = Distributor()
var r1 = Recorder()
var r2 = Recorder()
d.register(r1.listener)
d.register(r2.listener)
d.distribute(10)
print(Recorder.events) // [10, 10] Same event recorded twice.
The above compiles and runs. But I want events
in Recorder
to be an instance member so that each Recorder has its own record. Removing static
throws the compiler error: instance member 'events' cannot be used.
I have tried defining an instance func record(event)
in Recorder for handleEvent(event)
to call, but I get the same error.
Marius's answer (in Instance member cannot be used on type | Closures) suggests you can't access instance members while properties are being defined so I also tried to compute listener later like this.
class Recorder {
var events = [Int]()
var listener: EventListener {
class R : EventListener {
func handleEvent(event: Int) {
events.append(event) // error: can't access events
print("Recorded: \(event)")
}
}
return R()
}
}// Recorder
But the compiler says it can't access the the outer self.
Closures seem pretty impotent if they can't access outer selfs. In Java, you can get to outer selfs with something like Recorder.self.events
. And Recorder.self.
might only be necessary if there are name clashes(?)
Is Swift designed to be this way or what am I missing?
How would you write it so Recorder
gives Distributor
an object that can do nothing but receive handleEvent messages?
Thanks so much.