2016-05-16 5 views
5

Ich habe folgendes Protokoll und seine ErweiterungSwift-Protokoll mit zugehörigem Typ - Typ selbst nicht verweisen kann als Anforderung

public protocol RESEndpointReachable: CustomDebugStringConvertible 
{ 
    associatedtype EndpointType: RESEndpointReachable 


    // MARK: - Properties 

    /// The name of the endpoint as defined in the REST URI. 
    var name: String { get } 

    /// An array of possible next endpoints that this endpoint can reach. E.g account's next endpoints would be authenticate and unauthenticate. 
    var nextPossibleEndpoints: [EndpointType] { get } 


    // MARK: - Ability 

    /// Used to process the endpoint. 
    func processRequest(request: RERequest) 

    /// Processes the next endpoint that matches the name `name`. Expects an endpoint with the name `name` to exist in `nextPossibleEndpoints`. 
    func processNextEndpointWithName(name: String, request: RERequest) 
} 

public extension RESEndpointReachable 
{ 
    // MARK: - CustomDebugStringConvertible 

    public var debugDescription: String { 
     return name 
    } 


    // MARK: - RESEndpointReachable 

    var nextPossibleEndpoints: [EndpointType] { 
     return [] 
    } 

    public func processRequest(request: RERequest) 
    { 
     // Check all possible endpoints are being processed 
     if let nextEndpoint = nextPossibleEndpoints.first 
     { 
      fatalError("Unhandled endpoint \(nextEndpoint).") 
     } 
    } 

    public func processNextEndpointWithName(name: String, request: RERequest) 
    { 
     // Get the next endpoint that matches the specified name 
     let nextEndpoints = nextPossibleEndpoints.filter { $0.name == name } 

     if nextEndpoints.count > 1 
     { 
      fatalError("Multiple next endpoints found with the name '\(name)'.") 
     } 

     guard let nextEndpoint = nextEndpoints.first else 
     { 
      fatalError("No next endpoint with the name '\(name)'.") 
     } 


     // Process the next endpoint 
     nextEndpoint.processRequest(request) 
    } 
} 

auf Gebäuden, die Linie associatedtype EndpointType: RESEndpointReachable hat den folgenden Fehler: Type may not reference itself as a requirement. Aber so wie ich es verstehe, benutzt man so verwandte Typen in Swift.

Wie Sie vielleicht geraten haben, möchte ich immer, was auch immer EndpointType wird als ein Typ, der von RESEndpointReachable erbt festgelegt wird.

+0

Ich nicht diese Funktion ist möglich blue jetzt! Ref: https://gist.github.com/curtclifton/1923a47774a94e904bf0 https://forums.developer.apple.com/thread/15256. Compiler läuft in rekursiven Loops – sargeras

+0

Danke :) Ich dachte, das könnte der Fall sein ... Vielleicht nächsten Monat ... –

Antwort

3

Diese Funktion wird vom Swift-Team als 'rekursive Protokolleinschränkungen' bezeichnet und befindet sich in der Roadmap, die in einer zukünftigen Version von Swift hinzugefügt werden soll. Weitere Informationen zu diesem und anderen geplanten Features finden Sie im Swift Team 'Completing Generics' manifesto.

+0

Scheint mir lächerlich, dass Swift 4 immer noch nicht unterstützt -.- – d4Rk

+0

Laut Doug Gregor Kommentar In der Problemverfolgung (https://bugs.swift.org/browse/SR-1445) wurde es mit Swift 4.1 veröffentlicht, daher wird der neueste Xcode _should_ mit einem Compiler ausgeliefert, der dies unterstützt. (Habe es nicht selbst versucht, also weiß ich nicht, wie gut das Feature in der Praxis funktioniert ...) – AustinZ

1

Ja, das ist nicht OK mit swift. Ein Protokoll kann es selbst nicht als Typbeschränkung verwenden. Eine Lösung besteht darin, ein zusätzliches Protokoll zu deklarieren, das RESEndpointReachable selbst adoptieren wird und die Einschränkung RESEndpointReachable zu diesem Superprotokoll.

nahm ich das Beispiel aus dem Buch iOS 10 Programming Fundamentals mit Swift von Neuburg M. (siehe Seite 194 sehen)

illegal Beispiel:

1 protocol Flier { 
    2   associatedtype Other : Flier 
    3   func flockTogetherWith(_ f: Other) 
    4 } 
    5 
    6 struct Bird : Flier { 
    7   func flockTogetherWith(_ f: Bird) {} 
    8 } 

Lösung:

1 protocol Superflier {} 
    2 protocol Flier: Superflier { 
    3   associatedtype Other : Superflier 
    4   func flockTogetherWith(_ f: Other) 
    5 }  
    6 
    7 struct Bird : Flier { 
    8   func flockTogetherWith(_ f: Bird) {} 
    9 } 

Prost