Clean Swift Workshop

2ddd3d3e0d92ad45884bdcbef3a514a8?s=47 Chiaote Ni
November 08, 2020

Clean Swift Workshop

2ddd3d3e0d92ad45884bdcbef3a514a8?s=128

Chiaote Ni

November 08, 2020
Tweet

Transcript

  1. Clean Swift A better architecture to make project testable iOS@Taipei

    艾倫 Ni & William Kuo
  2. What is Clean Swift?

  3. ViewController

  4. Scene

  5. Interactor Presenter ViewController

  6. ViewController Interactor Presenter Display
 Logic Business
 Logic Presentation
 Logic ViewController

    Interactor Presenter Display
 Logic Business
 Logic Presenta tion
 Logic
  7. ViewControll Interact Presenter Display
 Logic Business
 Logic Presentation
 Logic Worker

    Worker Worker
  8. Worker ORM / DB Local API Network / API Network

    API ViewControll Interact Presenter Display
 Logic Business
 Logic Presentation
 Logic
  9. Worker ViewControll Interact Presenter Display
 Logic Business
 Logic Presentation
 Logic

    I13N Calculate Thumbnail resize Parse video’s metadata
  10. Interactor Presenter ViewController Request Response ViewModel

  11. None
  12. Boundary

  13. viewContorller interactor presentor in out in out DisplayLogic in out

    Boundary Boundary Boundary BusinessLogic Presentation Logic
  14. protocol MeetupEventListDisplayLogic: AnyObject { func displayMeetupEvents(viewModel: MeetupEventList.FetchEvents.ViewModel) func displayUpdateHistoryEvent(viewModel: MeetupEventList.UpdateHistoryEvent.ViewModel)

    } final class MeetupEventListViewController: UIViewController, MeetupEventListDisplayLogic { } protocol MeetupEventListBusinessLogic { func fetchMeetupEvents(request: MeetupEventList.FetchEvents.Request) func tapFavorite(request: MeetupEventList.TapFavorite.Request) func subscribeFavoriteUpdate(request: MeetupEventList.SubscribeFavoriteUpdate.Request) func unsubscribeFavoriteUpdate(request: MeetupEventList.UnsubscribeFavoriteUpdate.Request) } final class MeetupEventListInteractor: MeetupEventListBusinessLogic { } protocol MeetupEventListPresentationLogic { func presentMeetupEvents(response: MeetupEventList.FetchEvents.Response) func presentUpdateHistoryEvent(response: MeetupEventList.UpdateHistoryEvent.Response) } final class MeetupEventListPresenter: MeetupEventListPresentationLogic { }
  15. BusinessLogic in out Boundary private func private func private func

    private func Test
  16. What’s more?

  17. ViewController Interactor DataStore Router Data Passing Routing

  18. Workshop Practice

  19. None
  20. 基礎版 進階版

  21. None
  22. None
  23. Interactor Presenter ViewController Request Response ViewModel struct Request { }

    struct ViewModel { let historyEvents: [] let recentlyEvents: [] } struct Response { let recentlyEvents: [EventResponseItem] let historyEvents: [EventResponseItem] }
  24. enum MeetupEventList { enum FetchEvents { struct Request { }

    struct Response { let recentlyEvents: [EventResponseItem] let historyEvents: [EventResponseItem] } struct ViewModel { let historyEvents: [DisplayHistoryEvent] let recentlyEvents: [DisplayRecentlyEvent] } } }
  25. Presentation Model

  26. struct DisplayRecentlyEvent { let id: String let title: String let

    dateText: String let hostName: String let coverImageURL: URL? }
  27. struct DisplayHistoryEvent { let id: String let title: String let

    dateText: String let hostName: String let coverImageURL: URL? let favoriteButtonColor: UIColor }
  28. How?

  29. class MeetupEventListViewController: UIViewController { } var recentlyEvents: [MeetupEvent] = []

    var historyEvents: [MeetupEvent] = [] ViewController (MVC)
  30. var recentlyEvents: [MeetupEventList.DisplayRecentlyEvent] = [] var historyEvents: [MeetupEventList.DisplayHistoryEvent] = []

    protocol MeetupEventListDisplayLogic: AnyObject { func displayMeetupEvents( viewModel: MeetupEventList.FetchEvents.ViewModel ) } class MeetupEventListViewController: UIViewController, MeetupEventListDisplayLogic { } ViewController (Clean Swift)
  31. meetupEventListAPI.fetchMeetupEvents { [weak self] result in guard let self =

    self else { return } switch result { case let .success((recentlyEvents, historyEvents)): self.recentlyEvents = self.recentlyEvents self.historyEvents = self.historyEvents self.tableView.reloadData() case let .failure(error): print("#### error -> \(error)") } } loadData( ) (MVC)
  32. let request: MeetupEventList.FetchEvents.Request = .init() interactor?.fetchMeetupEvents(request: request) loadData( ) (Clean

    Swift)
  33. func configureCell(with meetupEvent: MeetupEvent) { titleLabel.text = meetupEvent.title hostNameLabel.text =

    meetupEvent.hostName if let eventDate = meetupEvent.date { dateLabel.text = getDateText(with: eventDate) } else { dateLabel.text = "" } coverImageView.image = nil if let coverImageUrl = meetupEvent.coverImageLink, let url = URL(string: coverImageUrl) { coverImageView.isHidden = false coverImageView.kf.setImage(with: url) } else { coverImageView.isHidden = true } } Configure Cell (MVC)
  34. func configureCell( with meetupEvent: MeetupEventList.DisplayRecentlyEvent ) { titleLabel.text = meetupEvent.title

    hostNameLabel.text = meetupEvent.hostName dateLabel.text = meetupEvent.dateText coverImageView.image = nil if let url = meetupEvent.coverImageURL { coverImageView.isHidden = false coverImageView.kf.setImage(with: url) } else { coverImageView.isHidden = true } } Configure Cell (Clean Swift)
  35. protocol MeetupEventListBusinessLogic { func fetchMeetupEvents( request: MeetupEventList.FetchEvents.Request ) } class

    MeetupEventListInteractor: MeetupEventListBusinessLogic{ var fetchMeetupEventWorker: MeetupEventListAPIWorker func fetchMeetupEvents( request:MeetupEventList.FetchEvents.Request ) { } } Interactor (Clean Swift)
  36. protocol MeetupEventListPresentationLogic { func presentMeetupEvents( response: MeetupEventList.FetchEvents.Response ) } class

    MeetupEventListPresenter:MeetupEventListPresentationLogic { func presentMeetupEvents( response: MeetupEventList.FetchEvents.Response ){ } } Presenter (Clean Swift)
  37. 活動時間: 每週⼆ pm: 8:30 ~ 10:00 (每⽉第⼀週休) 活動地點:線上聚會 || Meet.jobs

    辦公室 (感謝Meet.jobs 提供場地)
  38. 聯絡資訊(email) 聯絡資訊(LinkedIn) 我們在招⼈~
 beanfun!的iOS團隊需要你
 
 ⽬前我們正在以Clean Swift為主架構
 重構整個beanfun! App ⽬前預計明年1⽉會上線

    如果你對這個機會有興趣,想了解更多資訊 歡迎email給我,或加我LinkedIn聊聊唷
  39. 練習專案 完成版 Clean Swift 討論群

  40. Thanks for your attention.