Upgrade to Pro — share decks privately, control downloads, hide ads and more …

VIPERアーキテクチャ

 VIPERアーキテクチャ

第5回スタートアップiOS勉強会での発表資料

Ryoichi Izumita

November 17, 2016
Tweet

More Decks by Ryoichi Izumita

Other Decks in Programming

Transcript

  1. ࣗݾ঺հ • ࿨ઘా ྖҰ • @rizumita • גࣜձࣾLang-8ͰiOSΞϓϦ։ ൃΛ୲౰ •

    HiNative for iOS • εϓϥτΡʔϯͰͷ࢖༻ϒΩ͸ γϟʔϓϚʔΧʔωΦͱόϨϧ εϐφʔσί
  2. VIPER • Clean ArchitectureͷҰछʢͩͱࢥ͏ʣ • MVC/MVVMͳͲͷ໰୊Λղܾ • Router(Wireframe)͕ભҠϩδοΫΛ୲౰ • VIPER

    ≒ MVVM + Router (+ Interactor) • Interactor͕ϏδωεϩδοΫΛ୲౰ • MVVM(FRP)΍Redux(ReSwift)͸ϥΠϒϥϦʹґଘ͢Δ͕VIPER͸ґଘ͠ͳ͍ • FRPΛར༻͢Δ৔߹ͱൺ΂ͯελοΫτϨʔε͕෼͔Γ΍͍͢ • ςετ͠΍͍͢ • ֤ϨΠϠʔؒͷ઀ଓ͸DIΛ࢖͏ͱྑ͍ • ϑΝΠϧ͕ଟ͘ͳΓ͕ͪ • Segueͷར༻͸ۤख
  3. class TaskListWireframe { weak var presentedViewController: UIViewController? func presentViewController(navigationController: UINavigationController)

    { let controller = TaskListViewController(nibName: nil, bundle: nil) let presenter = TaskListPresenter() let interactor = TaskListInteractor() let dataManager = TaskListDataManager() controller.eventHandler = presenter presenter.userInterface = controller presenter.input = interactor interactor.output = presenter interactor.dataManager = dataManager presentedViewController = controller navigationController.pushViewController(controller, animated: true) } } ஫)Ұൠతʹ͸DIΛߦ͍·͢
  4. protocol TaskListViewProtocol: class { func show(tasks: [DisplayTask]) func show(errorMessage: String)

    } extension TaskListViewController: TaskListViewProtocol { func show(tasks: [DisplayTask]) { self.tasks = tasks tableView.reloadData() } func show(errorMessage: String) { // errorMessageΛදࣔ } } class TaskListViewController: UITableViewController { var eventHandler: TaskListModuleProtocol? fileprivate var tasks: [DisplayTask] = [] override func viewDidLoad() { super.viewDidLoad() // লུ eventHandler?.updateView() } // UITableViewDataSource͸লུ }
  5. extension TaskListPresenter: TaskListModuleProtocol { func updateView() { input?.findTasks() } }

    extension TaskListPresenter: TaskListInteractorOutputProtocol { func found(tasks: [Task]) { userInterface?.show(tasks: tasks.map(translate(task:))) } func occurred(error: AppError) { userInterface?.show(errorMessage: translate(error: error)) } } class TaskListPresenter { weak var userInterface: TaskListViewProtocol? var input: TaskListInteractorInputProtocol? } protocol TaskListModuleProtocol { func updateView() } protocol TaskListInteractorOutputProtocol: class { func found(tasks: [Task]) func occurred(error: AppError) }
  6. protocol TaskListInteractorInputProtocol { func findTasks() } class TaskListInteractor: TaskListInteractorInputProtocol {

    weak var output: TaskListInteractorOutputProtocol? var dataManager: TaskListDataManagerProtocol? func findTasks() { dataManager?.findTasks { [weak self] tasks, error in if let error = error { self?.output?.occurred(error: error) } else { self?.output?.found(tasks: tasks) } } } }
  7. protocol TaskListDataManagerProtocol { func findTasks(completion: ([Task], AppError?) -> ()) }

    class TaskListDataManager: TaskListDataManagerProtocol { func findTasks(completion: ([Task], AppError?) -> ()) { completion([Task(title: "First"), Task(title: "Second")], nil) } }
  8. class AddTaskWireframe { func presentAddTaskViewController(parent: UIViewController) { // ભҠίʔυ }

    } protocol TaskListWireframeProtocol { func presentAddInterface() } extension TaskListWireframe: TaskListWireframeProtocol { func presentAddInterface() { guard let controller = presentedViewController else { return } addTaskWireframe?.presentAddTaskViewController(parent: controller) } } class TaskListPresenter { var wireframe: TaskListWireframeProtocol? // লུ… } extension TaskListPresenter: TaskListModuleProtocol { func addNewTask() { wireframe?.presentAddInterface() } // লུ… }
  9. class TaskListPresenterTests: XCTestCase { class UserInterface: TaskListViewProtocol { var calledShowTasks

    = false func show(tasks: [DisplayTask]) { calledShowTasks = true } var calledShowErrorMessage = false func show(errorMessage: String) { calledShowErrorMessage = true } } class Input: TaskListInteractorInputProtocol { var calledFindTasks = false func findTasks() { calledFindTasks = true } } func testUpdateView() { let presenter = TaskListPresenter() let userInterface = UserInterface() let input = Input() presenter.userInterface = userInterface presenter.input = input presenter.updateView() XCTAssertTrue(input.calledFindTasks) } }