AbemaTVにおけるiOSアーキテクチャの課題解決 / Solving problems in AbemaTV iOS architecture

AbemaTVにおけるiOSアーキテクチャの課題解決 / Solving problems in AbemaTV iOS architecture

AbemaTV iOSの5年の運用の中で発生した設計課題とその解決方法について

D876775710dce31f1793fa7056879c66?s=128

Yusuke Morishita

January 30, 2020
Tweet

Transcript

  1. 15.

    ୈ̍ੈ୅"DUJPO func getElement() { dispatcher.isLoading.dispatch(true) APIClient.getElement() .do(onError: { [weak self]

    error in self?.dispatcher.error(error) // Τϥʔ }) .do(onCompleted: { [weak self] in self?.dispatcher.isLoading.dispatch(false) // ׬ྃ }) .subscribe(onNext: { [weak self] element in self?.dispatcher.element.dispatch(element) // ੒ޭ }) .disposed(by: disposeBag) }
  2. 16.

    ୈ̍ੈ୅%JTQBUDIFS final class Dispatcher { static let shared = Dispatcher()

    let element = DispatchSubject<Element>() let isLoading = DispatchSubject<Bool>() let error = DispatchSubject<Error>() }
  3. 17.

    ୈ̍ੈ୅4UPSF final class Store { static let shared = Store()

    let isLoading: Property<Bool> let element: Property<Element> init(dispatcher: Dispatcher) { // dispatcher͔ΒྲྀΕ͖ͯͨΠϕϯτΛbind͢Δ } }
  4. 18.

    ୈ̍ੈ୅6* override func viewDidLoad() { super.viewDidLoad() // ActionʹΠϕϯτΛൃՐ Action.shared.getElement() //

    ߋ৽͞Εͨঢ়ଶΛUIʹbind Store.shared.element.asObservable() .bind(to: titleLabel.rx.text) .diposed(by: disposeBag) }
  5. 23.

    ୈ̍ੈ୅ͷ՝୊ override func viewDidLoad() { super.viewDidLoad() // ঢ়ଶͷߋ৽·ͨ͸λςϤίͷ੾Γସ͑ΛϑοΫͯ͠tableViewΛϦϩʔυ Observable.combineLatest( Store.shared.repositories.asObservable(),

    rx.traitCollectionDidChange.asObservable() ) .observeOn(MainScheduler.instance) .subscribe(onNext: { [weak self] _ in self?.tableView.reloadData() }) .disposed(by: disposeBag) … }
  6. 26.

    ୈ̎ੈ୅7JFX4USFBN final class ViewStream { // Output let element: Property<Element>

    let isLoading: Property<Bool> init( // Input viewDidLayout: Observable<Void>, traitCollectionDidChange: Observable<Void>, // Dependency action: Action = .shared, store: Store = .shared ) { // InputͷΠϕϯτΛ΋ͱʹOutputΛ߹੒͢Δ } }
  7. 30.

    ୈ̎ੈ୅ͷ՝୊ class SearchViewStream { // Output let repositories: Property<[Repository]> private

    let _repositories = BehaviorRelay<[Repository]>(value: []) private let _search = PublishRelay<String>() private let disposeBag = DisposeBag() init( // Dependency action: Action = .shared store: Store = .shared ) { // Input ⇨ Output Logic } // Input func search(_ text: string) { _search.accept(text) } }
  8. 31.

    ୈ̎ੈ୅ͷ՝୊ class SearchViewStream { // Output let repositories: Property<[Repository]> private

    let _repositories = BehaviorRelay<[Repository]>(value: []) private let _search = PublishRelay<String>() private let disposeBag = DisposeBag() init( // Dependency action: Action = .shared store: Store = .shared ) { // Input ⇨ Output Logic } // Input func search(_ text: string) { _search.accept(text) } }
  9. 32.

    ୈ̎ੈ୅ͷ՝୊ class SearchViewStream { // Output let repositories: Property<[Repository]> private

    let _repositories = BehaviorRelay<[Repository]>(value: []) private let disposeBag = DisposeBag() init( // Input search: Observable<String> // Dependency action: Action = .shared store: Store = .shared ) { // Input ⇨ Output Logic } }
  10. 33.

    ୈ̎ੈ୅ͷ՝୊ class SearchViewStream { // Input let search = PublishRelay<String>()

    // Output let repositories: Property<[Repository]> private let _repositories = BehaviorRelay<[Repository]>(value: []) private let _search = PublishRelay<String>() private let disposeBag = DisposeBag() init( // Dependency action: Action = .shared store: Store = .shared ) { // Input ⇨ Output Logic } }
  11. 36.

    ୈ̏ੈ୅6OJP class SearchViewModel: UnioStream<SearchViewModel>, SearchViewModelType { struct Input: InputType {

    let search = PublishRelay<String>() } typealias State = NoState struct Output: OutputType { let repositories: Observable<[Repository]> } struct Extra: ExtraType { let action: Action let store: Store } static func bind(from dependency: Dependency<Input, State, Extra>, disposeBag: DisposeBag) -> Output { // Dependency ⇨ Output Logic return Output(repositories: ${repositoriesΛฦ͢ม਺}) } }
  12. 42.

    ࢀর w 'MVYXJUI3Y4XJGU w IUUQTTQFBLFSEFDLDPNEFLBUPUPSPqVYXJUISYTXJGU w .77. 'MVY w IUUQTTQFBLFSEFDLDPNNBSUZTV[VLJNWWNQMVTqVY

    w "CFNBJ04"SDIJUFDUVSF w IUUQTTQFBLFSEFDLDPNUPJLJBCFNBJPTBSDIJUFDUVSF w 6OJP w IUUQTTQFBLFSEFDLDPNNBSUZTV[VLJNWWNGBMTFTIJ[IVBOHXPGVSVGSBNFXPSLXPLBJGBEBP SVTJUJNVEFCBSBUVLJHBBUVUBTIJ[IVBOHXPUPOHTVSV