SwiftでNSTimerとかUIButtonを使うときはBlocksKit使うといいよ
Cocoaでは、引数にtarget
とselector
を取るメソッドがいくつかありますね。
NSTimer
の+ scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:
UIControl
の- addTarget:action:forControlEvents:
こういうメソッドを、純粋なSwiftのクラス--つまり、NSObjectを継承していないクラス--で使おうとすると、クラッシュを引き起こします。*1
実際にこのコードは実行時にクラッシュします。
class SwiftClass { init() { NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("privateFunc"), userInfo: nil, repeats: true) } private func privateFunc() { println("hello") } }
これを回避するには、単純にNSObjectから継承すれば済みます。 もう一つの手段としては、BlocksKitを使うことです。
- CocoaPodsなどでBlocksKitをプロジェクトに組み込む
- Objective-Cで実装されたBlocksKitをSwiftから使うために、ブリッジングヘッダ(
<#Project-name#>-Bridging-Header.h
)でBlokcsKitのヘッダを読み込む - BlocksKitが提供しているAPIを使う
コードで示します。これはクラッシュせずに動作し、SwiftClassがNSObjectを継承せずにNSTimerを使用できていることがわかります。
class SwiftClass { init() { NSTimer.bk_scheduledTimerWithTimeInterval(1.0, block: { (t) -> Void in println("hello") }, repeats: true) } }
BlocksKitを使用することで、コールバック関数を設定するコードとコールバック関数を同じ場所に書けますので、関心を集約することができます。 SwiftプロジェクトではBlocksKitの使用をオススメします。
違う話になるため細かい記述は避けますが、ブロックを使用する際に気をつけないと循環参照を引き起こすので、そこだけは気をつけましょう。