在Swift中,建议改变行为并使用闭包来“动态地”做某事,因此例如你可以有一个函数字典,名字为关键字,实现为值。
然而,有时你想简单地知道“怎么做”,这是这个问题的原因。
那么,如何动态调用一个Swift方法从它的名字作为字符串?
在Objective C中很简单:
[self performSelector:NSSelectorFromString(@"aSelector")];
但是在Swift中禁止了performSelector
有什么选择吗?
但是,如果你想使用performSelector来动态调用一个给定的方法只给它的String签名,但它不支持本机,我已经找到如何做到。
可以创建一个C替代performSelector:
>甚至在原生的swift类上工作(非objective-c)
>从字符串中选择一个选择器
然而,实现它的完整版本并不是那么直接,并且有必要在C中创建方法。
在C中我们有dlsym(),这个函数返回一个指向char符号的函数的指针。
好吧,阅读这个有趣的帖子:
http://www.eswick.com/2014/06/inside-swift/
我学到了很多关于swift的有趣的东西。
_TFC14FirstSwiftTest12ASampleClass13aTestFunctionfS0_FT_CSo8NSString
其中“self”值作为最后一个参数传递
总之,你可以直接从c端调用它,没有任何种类的桥接,足以重建正确的函数签名。
在上面的签名中,有项目的名称(FirstSwiftTest)和长度(14),类的名称(ASampleClass)和长度(12),函数的名称(aTestFunction)和长度(13 ),然后将其他值作为返回类型ecc ecc。有关其他详细信息,请参阅上一个链接
上面的函数,表示为:
class ASampleClass { func aTestFunction() -> NSString { println("called correctly") return NSString(string: "test") }
}}
好吧,在c方面,我能够创建这个功能
#include <stdio.h> #include <dlfcn.h> typedef struct objc_object *id; id _performMethod(id stringMethod,id onObject) { // ... // here the code (to be created) to translate stringMethod in _TFC14FirstSwiftTest12ASampleClass13aTestFunctionfS0_FT_CSo8NSString // ... id (*functionImplementation)(id); *(void **) (&functionImplementation) = dlsym(RTLD_DEFAULT,"_TFC14FirstSwiftTest12ASampleClass13aTestFunctionfS0_FT_CSo8NSString"); char *error; if ((error = dlerror()) != NULL) { printf("Method not found \n"); } else { return functionImplementation(onObject); // <--- call the function } return NULL }
然后在迅速的一边叫它
let sampleClassInstance = ASampleClass() println(_performMethod("aTestFunction",sampleClassInstance))
该函数导致这些语句打印在日志上:
正确调用
测试
所以应该不是很难在C中创建一个_performMethod()替代:
>自动创建函数签名(因为它似乎有一个逻辑:-)
>管理不同的返回值类型和参数
编辑
在Swift 2(也许在Beta3,我没有尝试)似乎performSelector()是允许的(你可以调用它只在NSObject子类)。检查二进制,似乎现在Swift创建静态函数,可以由performSelector特别调用。
我创建了这个类
class TestClass: NSObject { func test() -> Void { print("Hello"); } } let test = TestClass() let aSel : Selector = NSSelectorFromString("test") test.performSelector(aSel)
现在在二进制我找到了
000000010026d830 t __TToFC7Perform9TestClass4testfT_T_
在这个时候,我不太明白这背后的原因,但我会进一步调查