How do I get access to the class "self" instance to call class instance methods given the following code. If I try self.callSomeClassIntance(), as shown, I get a "A C function pointer cannot be formed fro a closure that captures context" error from the compiler. I trying info.callSomeClassInstance(), but this will give a "no member callSomeClassInstance" error. Code will fire time correctly if the one line of code xxxx.callSomeClassIntance() is removed.
import Foundation
class Foo {
func callSomeClassIntance() {}
func start() {
let runLoop : CFRunLoopRef = CFRunLoopGetCurrent();
var context = CFRunLoopTimerContext(version: 0, info: unsafeBitCast(self, UnsafeMutablePointer<Void>.self), retain: nil, release: nil, copyDescription: nil)
let timer : CFRunLoopTimerRef = CFRunLoopTimerCreate(kCFAllocatorDefault, 0.1, 3.0, 0, 0, cfRunloopTimerCallback(), &context);
CFRunLoopAddTimer(runLoop, timer, kCFRunLoopCommonModes);
CFRunLoopRun()
}
func cfRunloopTimerCallback() -> CFRunLoopTimerCallBack {
return { (cfRunloopTimer, info) -> Void in
print("Fire timer...")
// need self context here to call class instance methods
self.callSomeClassIntance()
}
}
}
We don't need to capture self
because we're already passing it in.
When you create the context for your timer, you're putting self
into a format that allows the C code to deal with it, a void pointer:
unsafeBitCast(self, UnsafeMutablePointer<Void>.self)
This code returns a void pointer to self
. And that's what you're passing in for the info
argument when you create your context.
Whatever you pass for the info
argument when you create your context is what is used to pass in for the info
argument of the CFRunLoopTimerCallback
function. So, we need to apply the inverse operation (unsafeBitCast(info, Foo.self)
) to that info
argument:
func cfRunloopTimerCallback() -> CFRunLoopTimerCallBack {
return { _, info in
let grabSelf = unsafeBitCast(info, Foo.self)
grabSelf.callSomeClassIntance()
}
}