从名称(以String格式)调用方法有时很有用.
在Swift中,建议改变行为并使用闭包来"动态地"执行某些操作,因此例如,您可以使用函数字典,将名称作为键,将实现作为值.
但是,有时你想简单地知道"怎么做",这就是这个问题的原因.
那么,如何从名称作为字符串开始动态调用Swift方法?
在Objective C中它很简单:
[self performSelector:NSSelectorFromString(@"aSelector")];
Run Code Online (Sandbox Code Playgroud)
但performSelector在Swift中被禁止
有没有其他选择?
Lom*_*baX 33
在Swift中,您应该使用闭包并改变您的方法.但是,如果你想使用performSelector动态调用只给它的String签名的方法,尽管它本身不支持,我已经找到了如何做到这一点.
可以为performSelector创建一个C替代方法:
然而,实现它的完整版本并不是那么简单,并且有必要在C中创建该方法.
在C中我们有dlsym(),一个返回指向char符号的函数的指针的函数.好吧,阅读这篇有趣的帖子:http: //www.eswick.com/2014/06/inside-swift/ 我学到了很多关于swift的有趣的东西.
Swift实例方法是具有特定签名的普通函数,如下所示
_TFC14FirstSwiftTest12ASampleClass13aTestFunctionfS0_FT_CSo8NSString
Run Code Online (Sandbox Code Playgroud)
其中"self"值作为最后一个参数传递
总之,你可以直接从c方面调用它而不需要任何桥接,重建正确的函数签名就足够了.在上面的签名,则该项目(FirstSwiftTest)和lenght(14)的名称,类的名称(ASampleClass)和lenght(12),功能(aTestFunction)和lenght的名称(13 ),然后其他值作为返回类型ecc ecc.有关其他详细信息,请查看上一个链接
上面的函数是这个的表示:
class ASampleClass
{
func aTestFunction() -> NSString
{
println("called correctly")
return NSString(string: "test")
}
Run Code Online (Sandbox Code Playgroud)
}
好吧,在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
}
Run Code Online (Sandbox Code Playgroud)
然后迅速调用它
let sampleClassInstance = ASampleClass()
println(_performMethod("aTestFunction", sampleClassInstance))
Run Code Online (Sandbox Code Playgroud)
该函数导致这些语句打印在日志中:
称为正确
测试
因此,在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)
Run Code Online (Sandbox Code Playgroud)
现在我发现二进制文件
000000010026d830 t __TToFC7Perform9TestClass4testfT_T_
在这个时候,我不明白这背后的原因,但我会进一步调查
您可以通过这种方式从String调用方法:
let foo = <some NSObject subclass instance>
let selectorName = "name"
foo.perform(Selector(selectorName))
Run Code Online (Sandbox Code Playgroud)
仅当您的类是子类时才可用 foo
小智 5
class MyClass:NSObject
{
required public override init() { print("Hi!") }
public func test(){
print("This is Test")
}
public class func static_test(){
print("This is Static Test")
}
}
if let c: NSObject.Type = NSClassFromString("TestPerformSelector.MyClass") as? NSObject.Type{
let c_tmp = c.init()
c_tmp.perform(Selector("test"))
c.perform(Selector("static_test"))
}
Run Code Online (Sandbox Code Playgroud)