Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[RxSwift] Input, Output #34

@seungchan2

Description

@seungchan2
2022-05-13.11.43.54.mov
import Foundation

import RxSwift

protocol ViewModelType {

    associatedtype Input
    associatedtype Output

    var disposeBag: DisposeBag { get set }

    func transform(input: Input) -> Output
}

associatedtype
associated type은 프로토콜의 일부로 사용되는 타입을 위한 placeholder 역할을 함

associated type은 정의하는 프로토콜이 채택되기 전까지 실제 타입이 명시되지 않음

import Foundation

import RxSwift
import RxCocoa

final class BeforeNAfterViewModel: ViewModelType {
   
    struct Input {
        let didBeforeAddButtonTapped: Signal<Void>
        let didAfterAddButtonTapped: Signal<Void>
        
    }
    
    struct Output {
        let isBeforeButtonHidden: Driver<Bool>
        let isAfterButtonHidden: Driver<Bool>
    }
    
    var disposeBag = DisposeBag()
    
    private let isBeforeButtonHidden = BehaviorRelay<Bool>(value: false)
    private let isAlbumHidden = BehaviorRelay<Bool>(value: false)
    
    private let isAfterButtonHidden = BehaviorRelay<Bool>(value: false)

    func transform(input: Input) -> Output {
        input.didBeforeAddButtonTapped
            .emit(onNext: { [weak self] in
                guard let self = self else { return }
                self.isBeforeButtonHidden.accept(!self.isBeforeButtonHidden.value)
            })
            .disposed(by: disposeBag)
        
        input.didAfterAddButtonTapped
            .emit(onNext: { [weak self] in
                guard let self = self else { return }
                self.isAfterButtonHidden.accept(!self.isAfterButtonHidden.value)
            })
            .disposed(by: disposeBag)
        
        isBeforeButtonHidden
            .subscribe(onNext: { [weak self] isSelected in
                if isSelected {
                    self?.isAlbumHidden.accept(false)
                }
            })
            .disposed(by: disposeBag)
        
        isAfterButtonHidden
            .subscribe(onNext: { [weak self] isSelected in
                if isSelected {
                    self?.isAlbumHidden.accept(false)
                }
            })
            .disposed(by: disposeBag)
        
        return Output (
            isBeforeButtonHidden: isBeforeButtonHidden.asDriver(),
            isAfterButtonHidden: isAfterButtonHidden.asDriver()
        )
    }
}
  private lazy var input = BeforeNAfterViewModel.Input (
        didBeforeAddButtonTapped: beforeNAfterView.beforeAddButton.rx.tap.asSignal(),
        didAfterAddButtonTapped: beforeNAfterView.afterAddButton.rx.tap.asSignal()
    )

  private func bind() {
        output.isBeforeButtonHidden.drive(onNext: {
            self.beforeNAfterView.beforeAddButton.isHidden = $0
            self.beforeNAfterView.beforeAlbumButton.isHidden = !$0
            self.beforeNAfterView.beforeCameraButton.isHidden = !$0
        })
            .disposed(by: disposeBag)
        
        output.isAfterButtonHidden.drive(onNext: {
            self.beforeNAfterView.afterAddButton.isHidden = $0
            self.beforeNAfterView.afterAlbumButton.isHidden = !$0
            self.beforeNAfterView.afterCameraButton.isHidden = !$0
        })
            .disposed(by: disposeBag)
            
    }

Input, Output의 지향점은 모든 사용자 이벤트를 ViewModel로 넘겨 비즈니스 로직을 ViewModel에서만 처리하도록 하는 것임

버튼의 탭 이벤트, 텍스트필드의 입력 이벤트 등을 전부 Input에 정의하고 View로 넘겨줄 데이터들을 Output에 정의해주면 됨.

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions