从名称(以String格式)中调用方法有时会很有用。
在Swift中,建议更改行为并使用闭包“动态”地进行操作,例如,您可以拥有一个函数字典,名称为键,实现为值。
但是,有时您只想简单地知道“怎么做”,这就是这个问题的原因。
那么,如何从名称作为字符串开始动态调用Swift方法?
在目标C中很简单:
[self performSelector:NSSelectorFromString(@"aSelector")];
但是performSelector
在Swift中被禁止
还有其他选择吗?
在Swift中,您应该使用闭包并更改方法。但是,如果要performSelector
仅使用字符串签名就可以动态调用方法,尽管本机不支持该方法,我已经找到了实现方法。
可以创建C语言替代performSelector:
但是,实现它的完整版本并不是那么简单,并且有必要在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))
该函数将这些语句打印在日志上:
称为正确
测试
因此,在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_
目前,我还不太了解其背后的原因,但我将进一步调查
问题内容: 苹果的Swift 文档指出 如果您正在Cocoa或Cocoa Touch中使用Foundation框架,则可以使用整个NSString API来调用您创建的任何String值 如果我有一个String对象,例如 如何执行类似String var的NSString操作? 问题答案: 经过一些研究,看起来不是一个函数,但是可以通过桥接到来访问。 在苹果公司关于将Swift与Cocoa和Ob
问题内容: 我有一个采用以下格式的包含: 星期四,2014年9月4日10:50:12 +0000 您知道如何将其转换为: 04-09-2014 ( dd-MM-yyyy ) 当然,使用 Swift 问题答案: 如果上述方法不起作用,则应采取以下措施:
问题内容: 出现错误: 无法使用类型为参数的列表进行调用 如何解决呢? 问题答案: 使用Xcode7beta6: 带有Xcode7发行版:
问题内容: swift在String上是否有trim方法?例如: 问题答案: 这是从的开头和结尾删除所有空白的方法。 (示例使用 Swift 2.0 进行了测试。) (示例使用 Swift 3+ 进行了测试。) 希望这可以帮助。
问题内容: 我正在尝试从Swift调用CCKeyDerivationPBKDF。 我已经在Project-Bridging-Header.h中导入了所需的标头: (顺便说一句,在我的项目中导入其他Objective C代码时,桥接头似乎正常工作)。 在Xcode中,我可以从.swift文件跳转到此处显示的定义: 最后,当我尝试像这样调用函数时: …我得到这个编译器错误: 无法使用类型为’(CCPB
我知道Java应用程序可以捆绑为Mac应用程序,带有JavaSwing或JavaFX驱动的用户界面,以及捆绑的Java运行时(JRE)。但是我想用Swift编写的Xcode构建一个本机应用程序,带有Cocoa用户界面,可以调用Java库来处理一些数据。 我需要调用捆绑的JRE,调用所需的库(JAR文件),传递对Mac存储中文件的引用(或者该文件的内容作为内存中的大字符串),并取回字符串(XML或C