Главное Авторские колонки Вакансии Образование
472 0 В избр. Сохранено
Авторизуйтесь
Вход с паролем

Комбинированные ViewController’ы и VIPER

В одном из проектов, в котором мы работали над iOS-приложением, перед нами стояла задача сделать экран, содержащий несколько вкладок вот что у нас получилось.
Мнение автора может не совпадать с мнением редакции

Здравствуйте, дорогие друзья! С вами на связи компания IT-Machine.

В одном из проектов, в котором мы работали над iOS-приложением, перед нами стояла задача сделать экран, содержащий несколько вкладок, причём сделать это так, чтобы при добавлении и удалении новых вкладок на экран нам не приходилось перелопачивать весь код. Этот опыт оказался довольно интересным для нас, так как мы отказались от «традиционного» подхода с использованием шаблона проектирования MVC в пользу VIPER. И сегодня нам бы хотелось поделиться этим опытом с вами.

Мы не будем вас здесь в мельчайших подробностях «грузить» тем, что такое VIPER и с чем его едят (об этом вы можете прочитать здесь), а так же рассказывать о том, как реализовать функционал того или иного экрана – этот творческий процесс мы оставим полностью на откуп вам, но мы постараемся доступным языком рассказать о том, каким образом структурировать ваше приложение, сделав каждый его экран (модуль) максимально независимым.

Ну что ж, приступим!

Пусть наш экран имеет подобную структуру:

b_57e26d3d4cf76.jpg

Header View содержит названия вкладок, которые будут лежать в Body. При нажатии на название вкладки в Header’e соответственно будут меняться экраны в Body.

Итак, само по себе слово VIPER является бэкронимом для View, Interactor, Presenter, Entity и Routing. Соответственно, наш модуль будет состоять из следующих классов: View – отображает то, что «говорит» Presenter; Interactor – бизнес-логика приложения; Presenter – запрашивает данные от Interactor’а и подготавливает к показу во View; Entity – сущности, которыми управляет Interactor; Router – навигация между модулями.

Выглядит это все следующим образом:

b_57e26d47cac73.jpg

Для того, чтобы настроить «общение» между элементами нашего модуля, необходимо реализовать input- и output-протоколы для View и Interactor’а, которые для удобства лучше будет вынести в отдельные заголовочные файлы.

View-протоколы (общение View и Presenter’а):

@protocol ViewInterfaceOutputView

@end

@protocol ViewInterfaceInputPresenter

@end

Interector-протоколы (общение Interactor’a и Presenter’a):

@protocol InteractorInterfaceInput

@end

@protocol InteractorInterfaceOutput

@end

Чтобы было удобнее работать и сделать наши вкладки максимально независимыми, разобьем наш модуль на несколько сабмодулей, которые будут отображаться в Body. Подобный подход позволит в дальнейшим, при необходимости, добавлять новые или же убирать ненужные экраны с минимальными затратами сил и времени. Header так же необходимо сделать отдельным сабмодулем. По своей сути и структуре сабмодули ничем не будут отличаться от нашего главного модуля, поэтому смело можете реализовывать в них те же самые классы и протоколы!

Немаловажным компонентом здесь так же является протокол DelegateInterface, благодаря которому мы сможем «управлять» нашими сабмодулями в главном модуле.

@protocol DelegateInterface

@end

Теперь, когда мы разобрались, как нам сконфигурировать наш модуль, поговорим о том, каким же образом происходит навигация внутри этого самого модуля. Ответ - очень просто! При нажатии на какую-либо из вкладок в Header’e, View тут же посылает сигнал в Presenter, где вызывается необходимый метод из DelegateInterface (этот метод мы реализуем в Presenter’e нашего модуля, если угодно - в главном Presenter’e) - там мы «говорим» Router’у, что в Body необходимо показать другой сабмодуль. Далее процедура стандартная для каждого модуля/сабмодуля: View спрашивает Presenter, что и как ей показывать, Presenter запрашивает данные у Interactor’a, подготавливает их к показу и дает ответ View. Вот, в общем-то, и все хитрости.

Упрощенно на схеме это можно представить следующим образом:

b_57e26d5528baa.jpg

Если ваше приложение будет состоять из нескольких модулей, то таким же образом вы можете осуществить навигацию между модулями, ведь сабмодули по своей сути, как вы уже могли догадаться, являются ни чем иным, как модулями внутри модуля. На этом наш рассказ подходит к концу.

Ссылка на демо-проект, в котором вы можете посмотреть, как описанное выше выглядит на практике: https://github.com/it-machine/Modeles-Lesson

Благодарим каждого из вас за внимание и надеемся, что для кого-то этот рассказ был полезен и стал отправной точкой для покорения новых высот в разработке под iOS.

+1
В избр. Сохранено
Авторизуйтесь
Вход с паролем
Комментарии
Выбрать файл
Блог проекта
Расскажите историю о создании или развитии проекта, поиске команды, проблемах и решениях
Написать
Личный блог
Продвигайте свои услуги или личный бренд через интересные кейсы и статьи
Написать

Spark использует cookie-файлы. С их помощью мы улучшаем работу нашего сайта и ваше взаимодействие с ним.