まず..これが唯一のパラメータです。あなたはこれを行う必要はありません(それを分解する)。例外がスローされると、署名を印刷できます。場合によっては、どのブロックが予想されているかを示すこともあります。
次に、動的セレクタを起動に関する私の意見を...
あなたの最良のオプションは、セレクタを行わないように..ですこれは、呼び出しが複数のパラメータが含まれている場合は特に痛みだ...
何のことができます。私はC++(Pimplイディオムからのアイデア.. COMMインターフェイスもこれをやっています)でこれを行い、Swift、Objective-C、Javaなどで動作します。
同じインターフェイスを持つプロトコルを作成するeをオブジェクトとして使用します。そのプロトコルを継承する拡張を作成します。次に、オブジェクトインスタンスをその拡張/インタフェース/プロトコルにキャストします。
インターフェイス/拡張/プロトコルポインタを使用して、必要な機能を呼び出します。
import UIKit
import MediaPlayer
@objc
protocol MPAProtocol { //Functions must be optional. That way you don't implement their body when you create the extension.
optional func availableRoutes() -> NSArray
optional func discoveryMode() -> Int
optional func fetchAvailableRoutesWithCompletionHandler(completion: (routes: NSArray) -> Void)
optional func name() -> NSString
}
extension NSObject : MPAProtocol { //Needed otherwise casting will fail!
//Do NOT implement the body of the functions from the protocol.
}
使用法:
#import <Foundation/Foundation.h>
@interface NSObject (MPAVRoutingControllerProtocol)
- (void)fetchAvailableRoutesWithCompletionHandler:(void(^)(NSArray *routes))completion;
@end
@implementation NSObject (MPAVRoutingControllerProtocol)
@end
:あなたが拡張+プロトコルを作成するのではなく、ブリッジのヘッダーでそれを行うとしたら
let MPAVRoutingControllerClass: NSObject.Type = NSClassFromString("MPAVRoutingController") as! NSObject.Type
let MPAVRoutingController: MPAProtocol = MPAVRoutingControllerClass.init() as MPAProtocol
MPAVRoutingController.fetchAvailableRoutesWithCompletionHandler! { (routes) in
print(routes);
}
は、あなたが単一のObjective-Cのカテゴリを行うだけだろうその後
:
let MPAVRoutingControllerClass: NSObject.Type = NSClassFromString("MPAVRoutingController") as! NSObject.Type
let MPAVRoutingController = MPAVRoutingControllerClass.init()
MPAVRoutingController.fetchAvailableRoutesWithCompletionHandler! { (routes) in
print(routes);
}
最後に、プロトコル注入を使用することができれば、これをはるかに簡単に行うことができます:
func classFromString(cls: String, interface: Protocol?) -> NSObject.Type? {
guard let interface = interface else {
return NSClassFromString(cls) as? NSObject.Type
}
if let cls = NSClassFromString(cls) {
if class_conformsToProtocol(cls, interface) {
return cls as? NSObject.Type
}
if class_addProtocol(cls, interface) {
return cls as? NSObject.Type
}
}
return nil
}
func instanceFromString<T>(cls: String, interface: Protocol?) -> T? {
return classFromString(cls, interface: interface)?.init() as? T
}
@objc
protocol MPAProtocol {
optional func availableRoutes() -> NSArray
optional func discoveryMode() -> Int
optional func fetchAvailableRoutesWithCompletionHandler(completion: (routes: NSArray) -> Void)
optional func name() -> NSString
}
let MPAVRoutingController: MPAProtocol = instanceFromString("MPAVRoutingController", interface: MPAProtocol.self)!
MPAVRoutingController.fetchAvailableRoutesWithCompletionHandler! { (routes) in
print(routes);
}
要求されたクロージャのシグネチャ、つまり「オブジェクト」は間違いなく正しいのですか?プライベート関数は必ず何かのためにクロージャーを使用し、別のパラメーターを渡そうとするとエラーが発生します。また、swift_performSelectorはオブジェクトパラメータのクロージャも受け入れますか?その第三者のlibの医者はそれについて何を言っていますか? – Gero
申し訳ありません私はメソッドシグネチャを貼り付けたと思ったが、私は何か他のものを貼り付けた。 sigは、リバースエンジニアリングヘッダファイル(https://github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks)に従って、 ' - (void)fetchAvailableRoutesWithCompletionHandler :(id/* block * /)arg1;'です。 /MediaPlayer.framework/MPAVRoutingController.h)。ライブラリについては、私はちょうどそれをスクラップし、Obj-Cのアプリケーションのこのセクションを書き、後でそれをブリッジする –
ダング、それはそれを明確にしていない、重要な部分がコメントアウトされる原因になります。しかし、実際に '(^)(parameterTypes) '部分を削除したとすると、少なくとも' id'(つまり、 'AnyObject'を即座に返す)のように見えるように見えます。私はヘッダーを次のように理解しています: "ブロックに' id'を返して渡してください。だから多分 '/ * ... */withObject:{() - > AnyObject in/*はダミーオブジェクトを定義し、それを返す/ *})' 'と試してみてください。通常、設定するパラメータを正確に知らなくても、リバースエンジニアリングされたメソッドを呼び出すのは、少なくとも私の経験からは、すぐに南下します。 – Gero