3

次のコードを指定して、クラス「自己」インスタンスにアクセスして、クラス インスタンス メソッドを呼び出すにはどうすればよいですか。示されているように、self.callSomeClassIntance() を試すと、コンパイラから「コンテキストをキャプチャするクロージャから AC 関数ポインタを形成できません」というエラーが表示されます。info.callSomeClassInstance() を試してみましたが、「メンバーがありません callSomeClassInstance」というエラーが発生します。コード xxxx.callSomeClassIntance() の 1 行を削除すると、コードは正しく起動します。

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()
        }

    }
}
4

2 に答える 2

2

selfすでに渡しているので、キャプチャする必要はありません。

タイマーのコンテキストを作成するときはself、C コードがそれを処理できるようにする形式、つまり void ポインターに入れます。

unsafeBitCast(self, UnsafeMutablePointer<Void>.self)

このコードは への void ポインタを返しますselfinfoこれは、コンテキストを作成するときに引数として渡すものです。

infoコンテキストを作成するときに引数に渡すものは何でも、関数の引数に渡すために使用されinfoますCFRunLoopTimerCallback。したがって、その引数に逆演算 ( unsafeBitCast(info, Foo.self)) を適用する必要があります。info

func cfRunloopTimerCallback() -> CFRunLoopTimerCallBack { 
    return { _, info in
        let grabSelf = unsafeBitCast(info, Foo.self)
        grabSelf.callSomeClassIntance()
    }
}
于 2016-03-29T01:19:18.700 に答える