Комментарии 9
Как решаете проблему поиска topController, если в момент поиска может идти анимация показа другого экрана?
Сам поиск будет работать корректно, потому что presentedViewController или кастомное поле экрана-контейнера будет обновлено сразу, до начала анимации. Если же вы имеете в виду выполнение перехода во время анимации показа другого экрана, то тут есть два случая:
1) Автоматическая навигация выполняется как шаг в единой серии переходов на какой-то экран (например серия «переключение вкладки + push в navigation controller» как части единого перехода в конкретный чат). В этом случае очередной шаг будет выполняться после окончания анимации предыдущего.
2) Переход выполняется, когда уже начал показываться другой экран и эти действия происходит независимо. Тогда можно выяснять состояние активного экрана, возможно ли прямо сейчас показать новый экран сверху него и, возможно, подписываться на изменение этого состояния. Как именно это сделать — часто зависит от типа перехода и это уже детали реализации.
1) Автоматическая навигация выполняется как шаг в единой серии переходов на какой-то экран (например серия «переключение вкладки + push в navigation controller» как части единого перехода в конкретный чат). В этом случае очередной шаг будет выполняться после окончания анимации предыдущего.
2) Переход выполняется, когда уже начал показываться другой экран и эти действия происходит независимо. Тогда можно выяснять состояние активного экрана, возможно ли прямо сейчас показать новый экран сверху него и, возможно, подписываться на изменение этого состояния. Как именно это сделать — часто зависит от типа перехода и это уже детали реализации.
В демо проекте в ChatViewController почему-то self.chatId = "" вместо self.chatId = chatId. Из-за этого экран Contact 1 создается несколько раз, если тапать на экране Profile по Go to Contact 1.
Очень близко к вот этой реализации имхо. Крутится вокруг одного и того же — иерархия графа контроллеров.
https://github.com/ekazaev/route-composer
Спасибо за ссылку, на первый взгляд действительно похоже
Мы применяли этот подход в нескольких приложениях и остались очень довольны. Пока не нашли варианта который бы не покрывался данным подходом. Плюс отзывы сторонних разработчиков использующих библиотеку благоприятные. Что в общем то говорит что итерация по дереву пожалуй идеальный и не громоздкий подход. Особенно когда диплинкинг важен и из любого состояния приложение нужно переиначить в требуемое или используется подход с A/B тестированием.
Судя по демо-проекту у вас транзишн привязан к конкретному контексту, соответственно ViewControllerContextTransitionProvider выглядит спорно, в большом проекте switch станет огромным. Похожая ситуация с ViewControllersByContextFactory, только тут switch будет еще больше.
Возможно имеет смысл создавать отдельную реализацию для каждого ViewControllerContext, которая будет хранить в себе всю необходимую информацию о переходе. Количество файлов в проекте вырастет, но зато мы получим тайп-сейф инициализаторы контекста, конфигурация контроллеров будет инкапсулирована внутри контекста, плюс отпадет необходимость в реализации ViewControllerContextInfo, энума ScreenType, который в реальном проекте может может иметь 50+ значений; исчезнет огромный switch из ViewControllersByContextFactory.
Что-то вроде этого:
А методы свитчера и холдера будут иметь generic-спецификацию:
Возможно имеет смысл создавать отдельную реализацию для каждого ViewControllerContext, которая будет хранить в себе всю необходимую информацию о переходе. Количество файлов в проекте вырастет, но зато мы получим тайп-сейф инициализаторы контекста, конфигурация контроллеров будет инкапсулирована внутри контекста, плюс отпадет необходимость в реализации ViewControllerContextInfo, энума ScreenType, который в реальном проекте может может иметь 50+ значений; исчезнет огромный switch из ViewControllersByContextFactory.
Что-то вроде этого:
protocol ViewControllerContext {
var transition: ViewControllerContextTransition { get }
func prepareController(using resolver: ContextResolver) -> UIViewController
}
struct ChatViewControllerContext: ViewControllerContext {
let chatId: String
let transition: ViewControllerContextTransition = NavigationControllerTransition()
func prepareController(using resolver: ContextResolver) -> UIViewController {
// ContextResolver – абстракция над вашим DI-контейнером etc.
return ChatViewController(chatId: chatId)
}
}
А методы свитчера и холдера будут иметь generic-спецификацию:
protocol ViewControllerContextHolder {
func hasSameContext<C: ViewControllerContext>(as other: C) -> Bool
}
protocol ViewControllerContextSwitcher {
func canSwitch<C: ViewControllerContext>(to context: C) -> Bool
func switchContext<C: ViewControllerContext>(to context: C, animated: Bool)
}
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Роутинг для iOS: универсальная навигация без переписывания приложения