Попытка вызвать селектор статической функции в Swift - PullRequest
0 голосов
/ 27 ноября 2018

Я пытаюсь добиться следующего, но сталкиваюсь с проблемами: -)

  • создать протокол, который могут принять подкласс UIViewController и UIView, который содержит один статический метод, который будет вызван в этом классе (назовите его configuration
  • Затем я хочу использовать среду выполнения targetC, чтобы найти классы, которые принимают этот протокол
  • В каждом из этих классов я хочу вызвать метод 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 Ответ

0 голосов
/ 27 ноября 2018

Технически вы можете заставить это работать.Пожалуйста, не надо.Это ужасный Свифт.Чтобы заставить это работать, вы должны подорвать все, что 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 »всегда завершается неудачей», но на самом деле это будет успешным.

После всего этого «donне делай этого, "как вы должны это сделать?С крышками.

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()
...