在 Swift 中,您应该使用闭包并改变您的方法。
但是,如果您想使用performSelector
动态调用仅给出字符串签名的方法,尽管本机不支持它,但我已经找到了如何做到这一点。
可以创建一个 PerformSelector 的 C 替代方案:
- 甚至可以在本地 Swift 类上工作(非 Objective-C)
- 从字符串中获取选择器
然而,实现它的完整版本并不是那么简单,有必要在 C 中创建该方法。
在 C 语言中,我们有 dlsym(),该函数返回一个指向给定 char 符号的函数的指针。
好吧,阅读这篇有趣的文章:http://www.eswick.com/2014/06/inside-swift/我学到了很多关于 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))
该函数导致这些语句打印在日志上:
正确调用
test
因此,在 C 中创建 _performMethod() 替代方案应该不那么困难:
- 自动创建函数签名(因为它似乎有一个逻辑:-)
- 管理不同的返回值类型和参数
EDIT
在 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)
现在在二进制文件中我发现
000000010026d830t__TToFC7Perform9TestClass4testfT_T_
目前,我不太明白这背后的原因,但我会进一步调查