When interfacing with the Objective-C runtime, it seems that selector names are allowed to have "illegal" characters. One can use this kind of selector to add new methods and call them in ways that would not be possible in code.
Let me give an example:
final class Test: NSObject {
@objc func test() {
print("This is Sparta!")
}
}
// Xcode indeed shows a warning "String literal is not a valid Objective-C selector"
let selector = Selector("invalid? !@#$%^&*()")
// let's add a new method, having the same implementation as an existing one
let testMethod = class_getInstanceMethod(Test.self, #selector(Test.test))!
let added = class_addMethod(Test.self, selector, method_getImplementation(testMethod), "v@:")
print("class_addMethod result: \(added)")
// let's see if calling the method works
Test().perform(selector)
The above code creates a selector with an invalid(?) name, uses the selector to add a new method to the test class, and calls that method afterward. Of course, one cannot directly call that method via the dot notation, as they would get a compiler error, however, the newly added method can be called via performSelector.
And to my surprise, the above code generates the following output:
class_addMethod result: true
This is Sparta!
This means that we can define, at runtime, methods with names that would generate compile errors if written in the class declaration.
I couldn't find any documentation supporting this behavior, intuitively since selector names are bare strings, dynamic method lookup should work with any kind of string.
Is this expected behavior? If yes, are there any limitations (except maybe length) on the contents of a selector name?