Попытка вызвать селектор статической функции в 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()
Другие вопросы по тегам