Typen, die schnell mehreren Protokollen entsprechen

77

Ich habe eine Objective-C-Variable, die mehreren Protokollen entspricht.

id <NSObject, NSCopying, NSCoding> identityToken; 

Wie würde ich diesen Typ in Swift darstellen?

Drew McCormack
quelle

Antworten:

151

Das sollte funktionieren:

var identityToken: NSObjectProtocol & NSCopying & NSCoding 

Beachten Sie, dass Sie schnell NSObjectProtocol anstelle von NSObject verwenden müssen.

Hier einige zusätzliche Beispiele:

Array von Objekten, die mehreren Protokollen entsprechen:

var array: [NSObjectProtocol & NSCopying & NSCoding]

Funktion mit einem Parameter, der mehreren Protokollen entspricht:

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

}

Verwenden Sie für die Swift-Version vor 3.1:

var identityToken: (NSObjectProtocol, NSCopying, NSCoding)
Connor
quelle
1
Können Sie erläutern, warum NSObjectProtocolverwendet werden muss?
Aleclarson
1
@aleclarson In Objective-C gibt es eine NSObject-Klasse und ein NSObject-Protokoll. Swift verwendet NSObject und NSObjectProtocol, um zwischen beiden zu unterscheiden.
Connor
8
Sehr cool. War sich dieser (etwas umständlichen) Syntax nicht bewusst. Wie können Sie dies jedoch auch mit einer expliziten Klasse tun, beispielsweise in obj-c : MyClass<ProtcolOne, ProtocolTwo>?
Devios1
4
@devios Sie können MyClass <ProtocolOne, ProtocolTwo> durch Generika ersetzen: func foo <T: MyClass wobei T: protocol <ProtocolOne, ProtocolTwo >> (params: T)
Oscar
3
@ Oscar danke für den hilfreichen Tipp. Wie kann man MyClass <ProtocolOne, ProtocolTwo> als Variable deklarieren?
Ilias Karim
11

Swift 3

var idToken: NSObjectProtocol & NSCopying & NSCoding

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

Anscheinend können Sie auch die zusammengesetzten Protokolle als Alias ​​eingeben, was nützlich sein kann, wenn Sie dieselbe Protokollkombination mehrmals verwenden möchten.

typealias IDToken = NSObjectProtocol & NSCopying & NSCoding

Gleiche Beispiele wie in der akzeptierten Antwort unter Verwendung eines Typ-Alias:

var idToken: IDToken

var array: [IDToken] = []

func foo(param: IDToken) { ... }
Phlippie Bosman
quelle
4

Die obige Antwort von conner ist richtig. Sie sollten jedoch häufig ein separates Protokoll implementieren, das selbst von den anderen Protokollen erbt und Ihnen mehr Flexibilität bietet, wenn Sie später zusätzliche Protokollmethoden hinzufügen oder die Protokolle der obersten Ebene ändern möchten.

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

Dann verwendet:

var identityToken : MyOtherProtocol
Joel Teply
quelle
0

Für Generika funktioniert dies auch:

func setCollectionViewDataSourceDelegate<D: UICollectionViewDataSource & UICollectionViewDelegate>
ScottyBlades
quelle