swift 带有无效字符的C-C选择器?

eoigrqb6  于 2024-01-05  发布在  Swift
关注(0)|答案(1)|浏览(137)

当与RIS-C运行时接口时,似乎允许选择器名称包含“非法”字符。可以使用这种选择器添加新方法,并以代码中不可能的方式调用它们。
让我给予一个例子:

  1. final class Test: NSObject {
  2. @objc func test() {
  3. print("This is Sparta!")
  4. }
  5. }
  6. // Xcode indeed shows a warning "String literal is not a valid Objective-C selector"
  7. let selector = Selector("invalid? !@#$%^&*()")
  8. // let's add a new method, having the same implementation as an existing one
  9. let testMethod = class_getInstanceMethod(Test.self, #selector(Test.test))!
  10. let added = class_addMethod(Test.self, selector, method_getImplementation(testMethod), "v@:")
  11. print("class_addMethod result: \(added)")
  12. // let's see if calling the method works
  13. Test().perform(selector)

字符串
上面的代码创建了一个具有无效(?)名称的选择器,使用该选择器向测试类添加一个新方法,并在之后调用该方法。当然,不能直接通过点表示法调用该方法,因为它们会得到编译器错误,但是,新添加的方法可以通过performSelector调用。
令我惊讶的是,上面的代码生成了以下输出:

  1. class_addMethod result: true
  2. This is Sparta!


这意味着我们可以在运行时定义方法,如果在类声明中编写,方法的名称将生成编译错误。
我找不到任何支持这种行为的文档,直观地说,由于选择器名称是空字符串,动态方法查找应该适用于任何类型的字符串。
这是预期的行为吗?如果是,选择器名称的内容是否有任何限制(可能除了长度)?

ddhy6vgd

ddhy6vgd1#

在Objetive-C的语法中,@selector的名字是Identifiers
标识符一个C++标识符是一个用于标识变量、函数或任何其他用户定义项的名称。标识符以字母A到Z或a到z或下划线开头,后跟零个或多个字母、下划线和数字(0到9)。
在标识符中不允许使用@、$和%等标点符号。在编程语言中,Manpower和manpower是两个不同的标识符。下面是一些可接受的标识符示例:

  1. myname50 _temp j a23b9 retVal

字符串
https://www.tutorialspoint.com/objective_c/objective_c_basic_syntax.htm
这是预期的行为吗?如果是,选择器名称的内容是否有任何限制(可能除了长度)?
我认为这是预期的行为; Obj-c运行时保留了一个选择器的哈希表,任何可以在NSString中编码和哈希的东西都应该工作,因此有效标识符的检查是在编译时而不是运行时进行的。

相关问题