Сделать свойство типа, а также соответствовать протоколу в Swift

Я хотел бы создать свойство определенного типа, а также соответствующее протоколу, что я бы сделал в Objective-C следующим образом:

@property (nonatomic) UIViewController<CustomProtocol> *controller;

Я ищу, чтобы указать, что свойство может быть установлено с объектом типа UIViewController, который также соответствует CustomProtocol, чтобы было ясно, что такое базовый класс. Я знаю, что мог бы просто использовать короткую заглушку класса, чтобы получить те же результаты, т.е.

class CustomViewController : UIViewController, CustomProtocol {}

Но это не похоже на самый чистый способ сделать это.


person sashimiblade    schedule 26.04.2015    source источник


Ответы (2)


Я не могу придумать хороший способ выразить это в Swift. синтаксис типа:

тип → тип массива | словарь | тип функции | идентификатор типа | тип кортежа | необязательный тип | неявно развернутый необязательный тип | протокол-композиция-тип | метатип-тип

То, что вы ищете, будет своего рода типом комбинации протоколов, который также принимает базовый класс. (тип комбинации протоколовprotocol<Proto1, Proto2, Proto3, …>.) Однако в настоящее время это невозможно.

Протоколы со связанными требованиями к типам могут иметь псевдонимы типов, которые определяют требуемый базовый класс и требуемые протоколы, но они также требуют, чтобы типы были известны во время компиляции, так что это вряд ли будет приемлемым вариантом для вас.

Если вы действительно в этом заинтересованы, вы можете определить протокол с частями интерфейса UIViewController, которые вы используете, использовать расширение для добавления соответствия, а затем использовать protocol<UIViewControllerProtocol, CustomProtocol>.

protocol UIViewControllerProtocol {
    func isViewLoaded() -> Bool
    var title: String? { get set }
    // any other interesting property/method
}

extension UIViewController: UIViewControllerProtocol {}

class MyClass {
    var controller: protocol<UIViewControllerProtocol, CustomProtocol>
}
person zneak    schedule 26.04.2015
comment
Верно. Это то, что мы должны делать. Просто определите протокол, в котором есть все, что нам может понадобиться, и расширьте такие вещи, как UIViewController, которые уже реализуют все эти методы, как соответствующие протоколу. - person nhgrif; 26.04.2015
comment
Я просто сделал заглушку класса, так как я развивался дальше, на самом деле оказалось, что это имеет для меня больше смысла, чем придерживаться протокола. Спасибо! - person sashimiblade; 27.04.2015
comment
Но как бы вы передали свой var controller методу UIKit, который ожидает UIViewControllers, а не протоколы UIViewController? Например navigiationController?.viewControllers = [controller] - person Daniel R; 06.04.2016
comment
@DanielR, тебе придется их разыграть. - person zneak; 06.04.2016

Теперь это возможно с помощью встроенной композиции:

var children = [UIViewController & NavigationScrollable]()

person jwswart    schedule 02.11.2017