2016-11-10 811 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) 
    } 
}