Типи, що швидко відповідають декільком протоколам


77

У мене є змінна Objective-C, яка відповідає декільком протоколам.

id <NSObject, NSCopying, NSCoding> identityToken; 

Як би я представив цей тип у Swift?

Відповіді:


151

Це має спрацювати:

var identityToken: NSObjectProtocol & NSCopying & NSCoding 

Зверніть увагу, що ви повинні швидко використовувати NSObjectProtocol замість NSObject.

Ось кілька додаткових прикладів:

Масив об'єктів, що відповідають декільком протоколам:

var array: [NSObjectProtocol & NSCopying & NSCoding]

Функція з параметром, який відповідає декільком протоколам:

func foo(param: NSObjectProtocol & NSCopying & NSCoding) {

}

Для версії Swift до 3.1 використовуйте:

var identityToken: (NSObjectProtocol, NSCopying, NSCoding)

1
Чи можете ви детальніше пояснити, чому NSObjectProtocolпотрібно використовувати?
aleclarson

1
@aleclarson У об'єктиві-c є клас і протокол NSObject. Swift використовує NSObject та NSObjectProtocol для розмежування між ними.
Коннор

8
Дуже круто. Не знав цього (дещо незграбного) синтаксису. Однак як ви можете зробити це і з явним класом, наприклад, у obj-c MyClass<ProtcolOne, ProtocolTwo>:?
devios1

4
@devios Ви можете замінити MyClass <ProtocolOne, ProtocolTwo>, використовуючи дженерики: func foo <T: MyClass де T: протокол <ProtocolOne, ProtocolTwo >> (params: T)
Оскар

3
@Oscar дякую за корисну пораду. як можна оголосити MyClass <ProtocolOne, ProtocolTwo> змінною?
Іліас Карім

11

Стрімкий 3

var idToken: NSObjectProtocol & NSCopying & NSCoding

func foo(_ delegateAndDataSource: UICollectionViewDelegate & UICollectionViewDataSource) { ... }

5

Здається, ви також можете ввести псевдонім складених протоколів, що може стати в нагоді, якщо ви плануєте використовувати одну і ту ж комбінацію протоколів кілька разів.

typealias IDToken = NSObjectProtocol & NSCopying & NSCoding

Ті самі приклади, що наведені у прийнятій відповіді, використовуючи псевдонім типу:

var idToken: IDToken

var array: [IDToken] = []

func foo(param: IDToken) { ... }

4

Наведена вище відповідь від conner є правильною, однак вам часто слід реалізовувати окремий протокол, який сам успадковується від інших протоколів, і надає вам більшу гнучкість, якщо ви захочете додати додаткові методи протоколу пізніше або змінити протоколи верхнього рівня.

internal protocol MyOtherProtocol : NSObjectProtocol, NSCopying, NSCoding {
    func someOtherNecessaryMethod()
}

Потім використовуються:

var identityToken : MyOtherProtocol

0

Для дженериків це також працює:

func setCollectionViewDataSourceDelegate<D: UICollectionViewDataSource & UICollectionViewDelegate>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.