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

VIPERアーキテクチャ

 VIPERアーキテクチャ

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

Adfa46c35fd59858d262497800c68df4?s=128

Ryoichi Izumita

November 17, 2016
Tweet

Transcript

  1. VIPERΞʔΩςΫνϟ גࣜձࣾLang-8 @rizumita / ࿨ઘా ྖҰ

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

    HiNative for iOS • εϓϥτΡʔϯͰͷ࢖༻ϒΩ͸ γϟʔϓϚʔΧʔωΦͱόϨϧ εϐφʔσί
  3. HiNative • ݴޠ΍ࠃʹ͍ͭͯ؆୯ʹ࣭໰ Ͱ͖Δɻ • iOS / Android / Web

    • https://hinative.com
  4. ຊ୊ʹೖΓ·͢

  5. AppleతMVC from developer.apple.com

  6. iOSΞϓϦʹ͓͚Δ MVCͷ໰୊఺ • ViewͱModel͕࿈ܞ͍ͯ͠ͳ͍ • ControllerʹΞϓϦέʔγϣϯϩδοΫ͕ूத • Controllerʹ͓͚Δը໘ભҠͰଞͷControllerʹґଘ

  7. iOSʹ͓͚ΔMVVM • AppleతMVCʹ͓͚ΔViewͱModel͕࿈ܞ͠ͳ͍໰୊Λ ղܾ • ModelϨΠϠʔͷઃܭ͸نఆ͞Ε͍ͯͳ͍ • ભҠϩδοΫͷ୲౰͕ෆ໌

  8. VIPER • Clean ArchitectureͷҰछʢͩͱࢥ͏ʣ • MVC/MVVMͳͲͷ໰୊Λղܾ • Router(Wireframe)͕ભҠϩδοΫΛ୲౰ • VIPER

    ≒ MVVM + Router (+ Interactor) • Interactor͕ϏδωεϩδοΫΛ୲౰ • MVVM(FRP)΍Redux(ReSwift)͸ϥΠϒϥϦʹґଘ͢Δ͕VIPER͸ґଘ͠ͳ͍ • FRPΛར༻͢Δ৔߹ͱൺ΂ͯελοΫτϨʔε͕෼͔Γ΍͍͢ • ςετ͠΍͍͢ • ֤ϨΠϠʔؒͷ઀ଓ͸DIΛ࢖͏ͱྑ͍ • ϑΝΠϧ͕ଟ͘ͳΓ͕ͪ • Segueͷར༻͸ۤख
  9. ద༻ • VIPER͸ϨΠϠʔΛ5ͭʹ ෼͚ΔͷͰখ͍͞ΞϓϦ ͩͱ࣮૷͕໘౗ɻ • ෳࡶ΋͘͠͸௕ظϓϩδΣ Ϋτʹద͢Δɻ ୹ظ ௕ظ

    ୯७ × ◦ ෳࡶ ◦ ˕
  10. ߏ଄ View Router (Wireframe) Presenter Interactor Entity Ϣʔβ ΞΫγϣϯ ߋ৽

    ໰͍߹Θͤ ௨஌
  11. 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Λߦ͍·͢
  12. 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͸লུ }
  13. 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) }
  14. 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) } } } }
  15. protocol TaskListDataManagerProtocol { func findTasks(completion: ([Task], AppError?) -> ()) }

    class TaskListDataManager: TaskListDataManagerProtocol { func findTasks(completion: ([Task], AppError?) -> ()) { completion([Task(title: "First"), Task(title: "Second")], nil) } }
  16. struct Task { let title: String } struct DisplayTask {

    let title: String }
  17. ભҠͷॻ͖ํ

  18. 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() } // লུ… }
  19. ςετͷॻ͖ํ

  20. 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) } }
  21. ٻਓ޿ࠂ • iOSΞϓϦΤϯδχΞΛืूͯ͠·͢ʂ