SwiftでObjctive-C id型の対応をclosureで逃げた話
仮にこういうObjective-Cのインターフェースがあったとする
番号を元にユーザーを検索する処理
- (void)searchForNumber:(int)number completionBlock:(id)block
このメソッドをSwift側で使いたい場合にid型なのでclosureが突っ込めないという自体になった場合の逃げの対策としてObjective-C側でBlocks型でラップする方向で回避できる
- (void)searchForNumber:(int)number completionUserBlock:(void (^)(User *))block
{
[self searchForNumber:number completionBlock:(id)block];
}
するとこう書ける
self.searchForNumber(10) { (user:User)->Void in
NSLog(user is \(user))
}
省略するとこうかな
self.searchForNumber(10) {
NSLog(user is \($0))
}
ポイントはインターフェースの末尾の引数がblock(closure)であること、それによりSwiftで使う場合に末尾の引数を()
の外に出せて書きやすくなる
これを利用することでオーバーロード的な使い方も可能になる
例えば検索結果としてユーザーに加えてサービスも追加になった場合はさっきと同じで以下のようにラップする
- (void)searchForNumber:(int)number completionUserAndServiceBlock:(void (^)(User *, Service *))block
{
[self searchForNumber:number completionBlock:(id)block];
}
するとSwift側はこうなる
self.searchForNumber(10) {
NSLog(user is \($0), service is \($1))
}
さっきと呼び出し方はあまり変えてないのに同じ書き方でパラメーターの取得ができるの超便利
場面としてそんな必要になることはないだろうけど、closureでレスポンス受け取るような場合はやってみるといいかも