Swift 2.2 Generics: невозможно преобразовать возвращаемое выражение типа ItemPageControllerFactory в возвращаемый тип T

У меня есть протокол ItemContainer и подкласс UIViewController ItemPageController, который соответствует протоколу.

У меня также есть протокол ItemContainerControllerFactory и структура, соответствующая этому протоколу.

Проблема: я хочу создать метод, возвращающий соответствующий подтип ItemControllerControllerFactory. Однако я получаю следующую ошибку компилятора: «Невозможно преобразовать возвращаемое выражение типа ItemPageControllerFactory в возвращаемый тип T»

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"
}

Есть идеи, что я делаю неправильно?


person Chylis    schedule 27.04.2016    source источник
comment
изменить return ItemPageControllerFactory() на return T()   -  person parveenkhtkr    schedule 27.04.2016
comment
Почему вы там используете дженерик? Возвращаемое значение имеет постоянный тип. Причина, по которой Swift жалуется, заключается в том, что вызывающий функцию не знает, что она возвращает, поскольку он никогда ничего не вводит в нее, чтобы можно было вывести тип T.   -  person Hamish    schedule 27.04.2016
comment
1) Если я заставлю его работать, он не будет жестко закодирован (я хочу иметь возможность возвращать разные типы ItemContainerControllerFactory) 2) Я думал, что T будет привязан к типу возврата (ItemPageControllerFactory), и, таким образом, вызывающий сможет вывести тип?   -  person Chylis    schedule 27.04.2016
comment
Вызывающий определяет тип универсального, а не функцию. Если вы хотите использовать разные виды подтипов, вам нужно будет идентифицировать их по родственному родительскому типу. В этом случае ItemContainerControllerFactory   -  person GetSwifty    schedule 27.04.2016


Ответы (1)


Чтобы создать общий экземпляр с такими протоколами, как вы, вам понадобится инициализатор в вашем протоколе.

что-то вроде этого:

protocol TestProtocol {
    init()
}

func create<T: TestProtocol>() -> T {
    return T()
}
person GetSwifty    schedule 27.04.2016
comment
Это не совсем то, что мне нужно. Я бы хотел, чтобы метод create в вашем примере решил, какой тип (действительных подтипов TestProtocol) мне вернуть. Вызывающий должен знать только об интерфейсе TestProtocol. - person Chylis; 27.04.2016
comment
Это была не ваша ошибка, поэтому я исправил ее :-) Если это действительно то, что вы делаете, вам не нужно использовать дженерики. - person GetSwifty; 27.04.2016
comment
Можно ли без дженериков описать следующий тип? связанный тип ContainerType: UIViewController, ItemContainer (например, UIViewController ‹ContainerType› в Objective-C) - person Chylis; 28.04.2016