I'm trying to achieve the following but am running into issues :-)
- create a protocol that UIViewController and UIView subclass can adopt
which contain one static method to be called on this class (call it
configuration
- I then want to use the objectiveC runtime to find the classes that adopt this protocol
- On each of those class I want to call the
configuration
method - The configuration method is to return a dictionary (key: a description string, value: a selector to be called on the class)
So far I was able to create the protocol, find the class implementing the protocol but i'm running into compiling issues.
Here is the protocol
@objc public protocol MazeProtocol: NSObjectProtocol{
@objc static func configurations() -> NSDictionary
}
Here is the extension to adopt the protocol on one of my class:
extension MapCoordinatorViewController: MazeProtocol {
static func configurations() -> NSDictionary {
let returnValue = NSMutableDictionary()
returnValue.setObject(#selector(test), forKey: "test" as NSString)
return returnValue
}
@objc static func test() {
print("test")
}}
and here is the code i'm using to try to call the selector returned from the configuration method:
let selectorKey = controllerClass.configurations().allKeys[indexPath.row]
let selector = controllerClass.configurations().object(forKey: selectorKey)
controllerClass.performSelector(selector) <================ error here
ControllerClass is declared as let controllerClass: MazeProtocol.Type
I get the following compile warning:
Instance member 'performSelector' cannot be used on type 'MazeProtocol'
What am I missing?
You can technically force this to work. Please don't. This is horrible Swift. To get this to work, you have to undermine everything Swift is trying to do. But yes, with warnings, you can technically get this to compile and work. Please, please don't.
First, you need to make
selector
be aSelector
. You're using anNSDictionary
, which is terrible in Swift, and so you getAny?
back. But, yes, you canas!
cast it into what you want:And then, defying all the type gods, you can just declare that classes are actually
NSObjectProtocol
, because why not?This will throw a warning "Cast from 'MapCoordinatorViewController.Type' to unrelated type 'NSObjectProtocol' always fails", but it will in fact succeed.
After all that "don't do this," how should you do this? With closures.