Swiftでは動的にメソッドを呼び出せない!
SwiftではperformSelector
が呼び出せないため、Swiftだけ行うと限界がみえてくる。
StackOverFlowに書かれているこの方法でも良いのだが、僕は同期で処理をさせたかったのでこの方法では都合が悪かった。
具体的に言うと、外部で作成したオブジェクトを自動的に別オブジェクトのインスタンス変数へ動的に設定したかったのだ。
そして、設定と同時にそのインスタンス変数を使って処理をしたかったのだ。
もちろん頑張ってコードを書けば動的メソッドを使わなくても可能だが、今後を考えるとなんとかしたい。
Cで対応、、、は見送り
そうすると、C言語を使って対応するStackOverFlowを見つけたが・・・
この方法は僕には理解ができないので、問題が発生すると対応ができない。よって却下。
Objective-cで対応
で、結局Objective-c
に頼ることにした。
こういう時は頼りになるなぁ。
Objective-cで作るのは以下の二つのファイル。
Meta.h
#import <Foundation/Foundation.h>
@interface Meta : NSObject
+ (void)call:(id)obj method:(NSString*)method withObject:(id)withObject;
@end
Meta.m
#import "Meta.h"
@implementation Meta
// 指定オブジェクトのメソッドを引数一つで呼び出す
+ (void)call:(id)obj method:(NSString*)method withObject:(id)withObject {
// 呼び出しメソッドのセレクターを用意
SEL sel = NSSelectorFromString([NSString stringWithFormat:@"%@:", method]);
// メソッドを呼び出します。
// 警告が出るので、以下サイトを見て回避してます。
// http://captainshadow.hatenablog.com/entry/20121114/1352834276
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[obj performSelector:sel withObject:withObject];
#pragma clang diagnostic pop
}
@end
作ったObjective-cのコードをSwiftで呼び出せる様にBridging-Header
に定義します。
Bridging-Header.hを知らない方はこちらを参照してください。
Bridging-Header.h
#import "Meta.h"
それをSwiftで呼び出します。
Meta.call(sampleObj(), method: "setHoge", withObject: Data())
callメソッドに関してはもう少し凝っても良いのだが、僕の場合はこの程度で十分だった。
余談
なぜかわからないのだが、Meta.h
のメソッド名を以下の様にした場合はコンパイルエラーが発生した。
Meta.h
+ (void)performSelectorClass:(id)obj method:(NSString*)method withObject:(id)withObject;
performSelectorというキーワードが使えない感じがした。