У меня есть архитектура VIPER, и я хочу создать родительский компонент поиска VIPER, который работает с универсальным типом. Идея проста, поэтому у меня есть панель поиска и табличный вид. Например, я могу показать названия напитков или продуктов в виде таблицы. Зависит от того, какой общий тип данных я указал, я хочу показать продукты или напитки.
Я нашел очень хороший пример, который решает мою проблему с универсальными контроллерами представлений. Но я хочу создать что-то подобное для быстрой универсальной архитектуры VIPER.
Я не буду описывать все классы VIPER, такие как (Router
, Interdictor
и т. д.).
Итак, у меня есть родительский контроллер представления:
BaseSearchViewController: UIViewController {
var presenter: BaseSearchPresenter<Any>?
}
и ребенок:
FoodSearchViewController: BaseSearchViewController {
}
Это родительский презентатор, указанный в BaseSearchViewController.
class BaseSearchPresenter<T> {
var items [T]
}
также у меня есть ведущий поиска детского питания с определенным типом еды, который я хотел бы отобразить в своей таблице:
class FoodSearchPresenter: BaseSearchPresenter<Food> {
}
Когда я пытаюсь настроить свой VIPER:
let viewController = FoodSearchViewController(...) // init VC
let presenter = FoodSearchPresenter()
viewController.presenter = presenter // assigning child FoodSearchPresenter instance to a BaseSearchViewController presenter variable leads to this error:
Cannot assign value of type 'FoodSearchPresenter' to type 'BaseSearchPresenter<Any>?'
Вот репо с проблемой.
спасибо за размещенную ссылку, да, я думаю, мне нужно больше узнать о дженериках. Единственное, что я понял из ссылки на мой вопрос, что BaseSearchPresenter<Any> — это не то же самое, что BaseSearchPresenter<Food>, поправьте меня, если я ошибаюсь. Но все еще есть проблема, как это реализовать.
viewController.presenter = presenter as? BaseSearchPresenter<Any>
если я делаю что-то подобное, у меня такая же проблема, как вы написали, может быть, я не понял.
Да, это будет та же проблема. Что касается основного вопроса, вам нужно вернуться к реальной проблеме, которую вы решаете в своем коде. Попытка построить что-то абстрактно-универсальное запутает вас. Начните с создания вашей системы с несколькими конкретными типами; затем извлеките фрагменты, в которых происходит дублирование. Не начинайте с универсального класса и не пытайтесь форсировать его. Начните с конкретной реализации и извлеките дженерик (в идеале не класс…, но все же что-то общее).
Как я вижу, вы используете класс Basket<T: Fruit>
, что вы имеете в виду в идеале не класс. Также я попробовал ваш код и компилятор выдал ошибку в методе инициализации. не уверен, что понимаю, что делать дальше ) спасибо за помощь!
Под «в идеале не класс» я просто подразумеваю, что Swift обычно поощряет композицию с протоколами и типами значений, а не наследование классов.
Я оставил комментарии о том, как решить эту проблему, но в вашем конкретном случае ответ заключается в том, что BaseSearchViewController должен быть универсальным.
class BaseSearchPresenter<T> {
var items: [T] = []
}
// BaseSearchViewController must be generic in order to vary its Element
class BaseSearchViewController<Element>: UIViewController {
var presenter: BaseSearchPresenter<Element>?
}
struct Food {}
class FoodSearchPresenter: BaseSearchPresenter<Food> {}
class FoodSearchViewController: BaseSearchViewController<Food> {}
let viewController = FoodSearchViewController()
let presenter = FoodSearchPresenter()
viewController.presenter = presenter
Что касается моего вопроса о начале бетона, я имею в виду начать с FoodSearchViewController
как с отдельной вещи. Не наследовать ни от чего, кроме UIViewController
. Затем создайте второй контроллер представления, который имел бы смысл в этом приложении и нуждался бы в чем-то подобном. потом извлекает общность между ними. Это, как правило, ведет вас в правильном направлении.
спасибо за ответ, странно сделал то же самое час назад =) у меня не работало и сейчас работает. Выложил в репо рабочий вариант, если smith спасибо за помощь!
Я считаю, что это дубликат stackoverflow.com/questions/30487258/swift-generics-upcasting/… Generics не является ковариантным.
BaseSearchPresenter<Food>
не является подтипомBaseSearchPresenter<Any>
. (Дайте мне знать, если вы думаете, что это не обман, и здесь больше вопросов, чем ответов там.)