Попытка вызвать селектор статической функции в Swift
Я пытаюсь добиться следующего, но сталкиваюсь с проблемами:-)
- создайте протокол, который UIViewController и подкласс UIView могут принять, который содержит один статический метод, который будет вызван для этого класса (вызовите его
configuration
- Затем я хочу использовать время выполнения ObjectiveC, чтобы найти классы, которые принимают этот протокол
- На каждом из этих классов я хочу назвать
configuration
метод - Метод конфигурации - вернуть словарь (ключ: строка описания, значение: селектор, вызываемый в классе)
До сих пор я был в состоянии создать протокол, найти класс, реализующий протокол, но я сталкиваюсь с проблемами компиляции.
Вот протокол
@objc public protocol MazeProtocol: NSObjectProtocol{
@objc static func configurations() -> NSDictionary
}
Вот расширение для принятия протокола на одном из моих классов:
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")
}}
и вот код, который я использую, чтобы попытаться вызвать селектор, возвращенный из метода конфигурации:
let selectorKey = controllerClass.configurations().allKeys[indexPath.row]
let selector = controllerClass.configurations().object(forKey: selectorKey)
controllerClass.performSelector(selector) <================ error here
ControllerClass объявлен как let controllerClass: MazeProtocol.Type
Я получаю следующее предупреждение компиляции:Instance member 'performSelector' cannot be used on type 'MazeProtocol'
Что мне не хватает?
1 ответ
Технически вы можете заставить это работать. Пожалуйста, не надо. Это ужасный Свифт. Чтобы заставить это работать, вы должны подорвать все, что Swift пытается сделать. Но да, с предупреждениями, вы можете технически заставить это скомпилировать и работать. Пожалуйста, пожалуйста, не надо.
Во-первых, вам нужно сделать selector
быть Selector
, Вы используете NSDictionary
, что в Swift ужасно, и так получается Any?
назад. Но да, вы можете as!
бросьте это в то, что вы хотите:
let selector = controllerClass.configurations().object(forKey: selectorKey) as! Selector
И затем, бросая вызов всем богам типов, вы можете просто объявить, что классы на самом деле NSObjectProtocol
потому что почему бы и нет?
(controllerClass as! NSObjectProtocol).perform(selector)
Это выдаст предупреждение "Преобразование из MapCoordinatorViewController.Type в несвязанный тип" NSObjectProtocol "всегда завершится неудачей", но на самом деле это удастся.
После всего этого "не делай этого", как ты должен это делать? С замыканиями.
public protocol MazeProtocol {
static var configurations: [String: () -> Void] { get }
}
class MapCoordinatorViewController: UIViewController {}
extension MapCoordinatorViewController: MazeProtocol {
static let configurations: [String: () -> Void] = [
"test": test
]
static func test() {
print("test")
}
}
let controllerClass = MapCoordinatorViewController.self
let method = controllerClass.configurations["test"]!
method()