Viperbase - это реализация архитектуры Viper для использования на платформе iOS.
Этот проект направлен на облегчение использования и усыновления Viper , облегчая все необходимые настройки для работы с этой архитектурой и пытаться как можно больше уменьшить ручную работу из -за ее характеристики.
Кокоподы являются менеджером зависимостей для какао -проектов. Чтобы интегрировать ViperBase в свой проект XCode, укажите ее в своем Podfile :
pod 'viper-base' , '~> 2.1' Самый плохой опыт, который у вас может быть при использовании Viper, - это создание самостоятельно , все файлы, классы и протоколы, необходимые для этой архитектуры. Это сильно влияет на производительность, что делает простую задачу занять много времени.
Xcode позволяет нам создавать персонализированные шаблоны. С помощью этого ресурса мы решили создать шаблон специально для ViperBase . Используя этот шаблон, больше не будет ручной работы.
Чтобы установить и использовать наш шаблон, проверьте этот урок.
Модуль представляет экран приложения.
Эта реализация Viper имеет некоторые особенности:
Некоторые подходы рассматривают задачу создания модуля как ответственность маршрутизатора . Но это нарушает принцип единственной ответственности , поскольку он уже отвечает за навигацию между модулями.
Чтобы решить эту проблему, был создан строитель . Он отвечает за создание всех компонентов модуля и создания соответствующих соединений.
Таким образом, сущности могут использоваться в одном или нескольких модулях, поскольку они представляют собой простые структуры без бизнес -логики.
Архитектура iOS, навигация выполняется из UiviewController в другой UiviewController . Из -за этого маршрутизатор должен владеть возрождением для представления текущего модуля, только для навигационной цели и получить представление о модуле назначения от его строителя.
Контракты определяют, как будет заключена связь между слоями. Модуль состоит из 5 контрактов:
Класс View соответствует этому протоколу. Он определяет связь от докладчика для просмотра
// MARK: - View Contract
protocol MyModuleViewProtocol : class {
} Класс докладчиков соответствует этому протоколу. Он определяет связь от просмотра к доступу
// MARK: - View Output Contract
protocol MyModuleViewOutputProtocol : class {
} Класс взаимодействия соответствует этому протоколу. Он определяет связь от докладчика к взаимодействию
// MARK: - Interactor Contract
protocol MyModuleInteractorProtocol : class {
} Класс докладчиков соответствует этому протоколу. Он определяет связь от интерактора к дошкольному
// MARK: - Interactor Output Contract
protocol MyModuleInteractorOutputProtocol : class {
} Класс маршрутизатора соответствует этому протоколу. Он определяет связь от докладчика с маршрутизатором
// MARK: - Router Contract
protocol MyModuleRouterProtocol : class {
} final class MyModuleView : UIViewController , VIPERView {
var presenter : MyModuleViewOutputProtocol !
}
// MARK: - MyModuleViewProtocol
extension MyModuleView : MyModuleViewProtocol {
}Вам просто нужно реализовать методы, определенные в договоре просмотра .
final class MyModulePresenter : VIPERPresenter {
weak var view : MyModuleViewProtocol !
var interactor : MyModuleInteractorProtocol !
var router : MyModuleRouterProtocol !
}
// MARK: - MyModuleViewOutputProtocol
extension MyModulePresenter : MyModuleViewOutputProtocol {
}
// MARK: - MyModuleInteractorOutputProtocol
extension MyModulePresenter : MyModuleInteractorOutputProtocol {
}Вам просто нужно реализовать методы, определенные в контракте с выводом представления и контрактом с выводом взаимодействия .
final class MyModuleInteractor : VIPERInteractor {
weak var presenter : MyModuleInteractorOutputProtocol !
}
// MARK: - MyModuleInteractorProtocol
extension MyModuleInteractor : MyModuleInteractorProtocol {
}Вам просто нужно реализовать методы, определенные в контракте Interactor .
final class MyModuleRouter : VIPERRouter {
weak var viewController : UIViewController !
}
// MARK: - MyModuleRouterProtocol
extension MyModuleRouter : MyModuleRouterProtocol {
}Вам просто нужно реализовать методы, определенные в контракте с маршрутизатором .
В маршрутизаторе навигация может быть сделана двумя способами: модульно представлять модуль или нажимать модуль на навигационный стек . Чтобы выполнить навигацию, используйте методы ниже:
- Presestmodule (Withview: Encedin: Animated: завершено :)
Этот метод представляет следующий модуль модально. Проверьте данные параметров ниже:
withView : Просмотр модуля для перемещения.embedIn : .navigationController или .none . Значение по умолчанию .noneanimated : будь то выполнять анимацию перехода. Значение по умолчанию truecompletion : обработчик позвонил, когда переход заканчивается. Значение по умолчанию nil- Pushmodule (Withview: Encedin: Animated :)
Этот метод выдвигает следующий модуль на навигационный стек . Он работает только в том случае, если текущий модуль встроен в контроллер навигации или является частью навигационного стека.
withView : Просмотр модуля для перемещения.embedIn : .navigationController или .none . Значение по умолчанию .noneanimated : будь то выполнять анимацию перехода. Значение по умолчанию true В классе Builder вы указываете соответствующие классы для View , Presenter , Interactor и router для модуля.
final class MyModuleBuilder : VIPERBuilder < MyModuleView , MyModulePresenter , MyModuleInteractor , MyModuleRouter > {
override class var defaultViewUIType : VIPERViewUIType {
return . storyboard ( name : " MyModuleView " , bundle : nil )
}
}
// MARK: - Builder custom methods
extension MyModuleBuilder {
} Вы также определяете, как будет загружен пользовательский интерфейс , через свойство defaultViewUIType . Есть 3 возможных значения:
. storyboard ( name : " MyModuleView " , bundle : nil ) . nib ( name : " MyModuleView " , bundle : nil ) . none4 метода ниже можно использовать для построения модуля. Кроме того, вы можете создавать пользовательские методы сборки в соответствии с потребностями модуля.
- строить() :
Создает модуль и возвращает конструкцию VIPERModule , содержащую view и ссылки presenter . Вы можете использовать ссылку на докладчика для передачи данных между модулями .
// MARK: - MyModuleRouterProtocol
extension MyModuleRouter : MyModuleRouterProtocol {
func goToNextModule ( ) {
let module = NextModuleBuilder . build ( )
pushModule ( withView : module . view )
}
}- Build (Viewustpe :) :
Этот метод работает как приведенный выше метод, но он позволяет указать тип пользовательского интерфейса во время вызова метода. Этот метод удобен, когда вы используете typealias для определения конфигурации модуля.
typealias MyModuleBuilder = VIPERBuilder < MyModuleView , MyModulePresenter , MyModuleInteractor , MyModuleRouter >
MyModuleBuilder . build ( viewUIType : . storyboard ( name : " MyModuleView " , bundle : nil ) )Вы также можете использовать этот метод, если вы намерены выполнить модульные тесты вокруг связи с модулем, издеваясь над одним или несколькими классами слоя , в соответствии с требованиями тестирования.
import XCTest
class ProjectTests : XCTestCase {
//...
func testModuleCommunication ( ) {
typealias MockModuleBuilder = VIPERBuilder < ModuleMockView , ModuleOriginalPresenter , ModuleOriginalInteractor , ModuleOriginalRouter >
let module = MockModuleBuilder . build ( )
//...
}
} - [устарел] Buildandattachtowindow ()
Это специальный метод сборки, обычно используемый для запуска начального модуля приложения, называемого в классе AppDelegate :
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = InitialModuleBuilder.buildAndAttachToWindow()
return true
}
}
[Обновлено]: Теперь вам нужно сначала построить модуль , используя методы build() или build(viewUIType:) , затем вызовите attachToWindow() или attachToWindow(withNavigationController:) Новые методы:
window = InitialModuleBuilder . build ( ) . attachToWindow ( ) window = InitialModuleBuilder . build ( ) . attachToWindow ( withNavigationController : true )[Важно]: планируется удалить устаревший метод в следующем крупном выпуске (v3.0)
- [устарел] BuildandattachtonavigationController (tabbaritem :)
Этот метод создает модуль, прикрепите его к контроллеру навигации и возвращает ссылку на навигационный контроллер . Если вы намерены использовать модуль внутри контроллера стержня , вы можете использовать параметр tabBarItem для настройки элемента панели вкладок для этого модуля.
let tabBarController = UITabBarController()
let bookmarksItem = UITabBarItem(tabBarSystemItem: .bookmarks, tag: 0)
let contactsItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 1)
let downloadsItem = UITabBarItem(tabBarSystemItem: .downloads, tag: 2)
tabBarController.viewControllers = [
BookmarksBuilder.buildAndAttachToNavigationController(tabBarItem: bookmarksItem),
ContactsBuilder.buildAndAttachToNavigationController(tabBarItem: contactsItem),
DownloadsBuilder.buildAndAttachToNavigationController(tabBarItem: downloadsItem)
]
[Обновлено]: Теперь вам нужно сначала построить модуль , используя методы build() или build(viewUIType:) , а затем вызовите attachToNavigationController() Новый метод:
window = MyModuleBuilder . build ( ) . attachToNavigationController ( )[Важно]: планируется удалить устаревший метод в следующем крупном выпуске (v3.0)
Если у вас есть конкретный модуль, который рассчитывает получить некоторые данные , удобно создать метод настраивания для этого модуля. Таким образом, строитель будет отвечать за передачу этих данных presenter .
Чтобы создать пользовательские методы сборки:
build() ;presenter в соответствии с реализацией;view . // MARK: - Builder custom methods
extension NextModuleBuilder {
static func build ( someData : Any , anotherData : Any ) -> MyModuleView {
let module = build ( )
module . presenter . someData = someData
module . presenter . anotherData = anotherData
return module . view
}
}Маршрутизаторы могут назвать этот строитель таким образом:
let view = NextModuleBuilder . build ( someData : " Example of data " , anotherData : " Another example of data " ) pushModule ( withView : view ) presentModule ( withView : view ) Viperbase выпускается по лицензии MIT.