当前位置: 首页 > 面试题库 >

在Swift中从String调用方法

司空高义
2023-03-14
问题内容

从名称(以String格式)中调用方法有时会很有用。
在Swift中,建议更改行为并使用闭包“动态”地进行操作,例如,您可以拥有一个函数字典,名称为键,实现为值。
但是,有时您只想简单地知道“怎么做”,这就是这个问题的原因。
那么,如何从名称作为字符串开始动态调用Swift方法?

在目标C中很简单:

[self performSelector:NSSelectorFromString(@"aSelector")];

但是performSelector在Swift中被禁止
还有其他选择吗?


问题答案:

在Swift中,您应该使用闭包并更改方法。但是,如果要performSelector仅使用字符串签名就可以动态调用方法,尽管本机不支持该方法,我已经找到了实现方法。

可以创建C语言替代performSelector:

  • 甚至可以在本机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))

该函数将这些语句打印在日志上:

称为正确
测试

因此,在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