2016-11-10 812 views
3

我想調用一個選擇器,帶有多個(2+)參數(可以確定參數的數量)。但是,選擇器在編譯時是未知的(實際上由NSSelectorFromString生成)。Swift中有NSInvocation的替代方案嗎?

在Objective-C中,我可以創建一個調用併爲其設置參數並對其進行調用。但是這在Swift中不可用。有沒有辦法解決? 像:

let obj = SomeClass() 
let selector = NSSelectorFromString("arg1:arg2:arg3:") //selector, arguments known only at runtime 
//invoke selector 
+0

你試圖解決什麼問題? – Alexander

+0

我很抱歉,但我正在爲客戶工作。但我會盡力描述它。我必須在配置文件的幫助下配置一個視圖,該配置文件可以根據需要進行配置。也就是說,可能的配置列表(每個嘗試訪問許多不同的方法)都很大。是的,他們可以按情況進行管理(將案例映射到方法),但我試圖使用通用解決方案來嘗試和管理此問題。 – Aswath

+0

這種代碼的動態性通常是糟糕的體系結構(沒有違法)的結果。有一些非常特殊的例外情況,但在95%的情況下,您不需要使用'NSInvocation',即使在Objective-C中也不應該使用。一種可能的解決方案是在字典中命名爲閉包,但即使這樣也有點代碼味道。 – Sulthan

回答

0

恐怕沒有辦法在斯威夫特做到這一點。

但是,您可能有一個Objective-C類來管理您的動態調用。你可以在那裏使用NSInvocation

3

雨燕3.1

NSInvocation可以動態地使用,而只是作爲一個有趣的練習,絕對不是重要的應用程序。有更好的alternatives

class Test : NSObject 
{ 
    var name : String? { 
     didSet { 
      NSLog("didSetCalled") 
     } 
    } 

    func invocationTest() { 
     let invocation : NSObject = unsafeBitCast(method_getImplementation(class_getClassMethod(NSClassFromString("NSInvocation"), NSSelectorFromString("invocationWithMethodSignature:"))),to:(@convention(c)(AnyClass?,Selector,Any?)->Any).self)(NSClassFromString("NSInvocation"),NSSelectorFromString("invocationWithMethodSignature:"),unsafeBitCast(method(for: NSSelectorFromString("methodSignatureForSelector:"))!,to:(@convention(c)(Any?,Selector,Selector)->Any).self)(self,NSSelectorFromString("methodSignatureForSelector:"),#selector(setter:name))) as! NSObject 
     unsafeBitCast(class_getMethodImplementation(NSClassFromString("NSInvocation"), NSSelectorFromString("setSelector:")),to:(@convention(c)(Any,Selector,Selector)->Void).self)(invocation,NSSelectorFromString("setSelector:"),#selector(setter:name)) 
     var localName = name 
     withUnsafePointer(to: & localName) { unsafeBitCast(class_getMethodImplementation(NSClassFromString("NSInvocation"), NSSelectorFromString("setArgument:atIndex:")),to:(@convention(c)(Any,Selector,OpaquePointer,NSInteger)->Void).self)(invocation,NSSelectorFromString("setArgument:atIndex:"), OpaquePointer($0),2) } 
     invocation.perform(NSSelectorFromString("invokeWithTarget:"), with: self) 
    } 
}