2016-04-27 10 views
1

Ich habe ein 'ItemContainer' Protokoll und UIViewController-Unterklasse 'ItemPageController', die mit dem Protokoll übereinstimmt.Swift 2.2 Generics: "Return-Ausdruck vom Typ ItemPageControllerFactory kann nicht in Return-Typ T konvertiert werden"

Ich habe auch ein 'ItemContainerControllerFactory' Protokoll und eine Struktur, die diesem Protokoll entspricht.

Das Problem: Ich möchte eine Methode erstellen, die einen entsprechenden ItemControllerControllerFactory-Untertyp zurückgibt. Allerdings habe ich den folgenden Compiler-Fehler: „Can not return Ausdruck vom Typ ItemPageControllerFactory konvertiert Typ T return“

protocol ItemContainer { 
    func navigateToItem(item:Item) 
} 

class ItemPageController : UIViewController, ItemContainer { 
    func navigateToItem(item:Item) { ... } 
} 

protocol ItemContainerControllerFactory { 
    associatedtype ContainerType : UIViewController, ItemContainer 
    func itemContainerController() -> ContainerType 
} 

struct ItemPageControllerFactory: ItemContainerControllerFactory { 
    typealias ContainerType = ItemPageController 

    func itemContainerController() -> ContainerType { 
     return ContainerType() 
    } 
} 

//Goal: Be able to return different ItemContainerControllerFactory depending on some logic... (Currently hard coded to ItemPageControllerFactory) 
func itemContainerFactory<T:ItemContainerControllerFactory>() -> T {  
    return ItemPageControllerFactory() //COMPILER ERROR: "Cannot convert return expression of type ItemPageControllerFactory to return type T" 
} 

Irgendwelche Ideen, was ich falsch mache?

+0

Änderung 'Rückkehr ItemPageControllerFactory()' auf 'Rückkehr T () ' – CodetrixStudio

+0

Warum verwenden Sie ein Generikum? Der Rückgabewert ist von einem konstanten Typ. Der Grund, warum sich Swift beschwert, ist, dass der Aufrufer der Funktion keine Ahnung hat, was sie zurückgibt, da sie niemals etwas in sie eingibt, damit der Typ von "T" abgeleitet werden kann. – Hamish

+0

1) Wenn ich es funktioniert, wird es nicht hart codiert werden (Ich möchte verschiedene ItemContainerControllerFactory-Typen zurückgeben) 2) Ich dachte, dass T an den Rückgabetyp (ItemPageControllerFactory) und damit den Aufrufer gebunden werden würde wäre in der Lage, auf den Typ zu schließen? – Chylis

Antwort

0

Um eine generische Instanz mit Protokolle zu erstellen, wie Sie sind, müssen Sie einen Initialisierer in Ihrem Protokoll

etwas wie folgt aus:

protocol TestProtocol { 
    init() 
} 

func create<T: TestProtocol>() -> T { 
    return T() 
} 
+0

Es ist nicht ganz das, was ich suche. Ich möchte die 'create' Methode in Ihrem Beispiel, um zu entscheiden, welcher Typ (von gültigen TestProtocol Subtypes) für mich zurückgibt. Der Anrufer sollte nur über die Schnittstelle 'TestProtocol' Bescheid wissen. – Chylis

+0

Das ist nicht, was Ihr Fehler war, also habe ich das behoben :-) Wenn das in der Tat ist, was Sie tun, müssen Sie keine Generika verwenden. – PeejWeej

+0

Kann der folgende Typ ohne Generika beschrieben werden? "associatedtype ContainerType: UIViewController, ItemContainer" (wie UIViewController in Objective-C) – Chylis

Verwandte Themen