안녕하세요 오늘은 내가 만든 함수를 bind(to: ~)에 사용하는 방법에 대해 포스팅하겠습니다.

View와 ViewModeld을 값을 바인딩할때 아래와 같은 코드를 사용합니다.

viewModel.output.text
	.bind(to: label.rx.text)
	.dispose(by: disposeBag)

String값을 Label에 쉽게 바인딩하고, Bool값을 isHidden에 바인딩해 손쉽게 실시간으로 변화하는 UI를 구현할 수 있습니다.

보통 자주 사용되는 컴포넌트나 디자인들을 미리 구현해두는데 이때 내가 만든 함수를 Binding 해서 사용하고싶다! 할때 Reacitve를 확장해 보다 편리하게 사용할 수 있습니다. 간단한 예제와 함께 확인해보겠습니다.

Binder 구현 전

class Button: UIButton {
	override init(frame: CGRect) {
    	self.backgroundColor = .black
        self.setTitleColor(.white, for: .normal)
    }
    
    func active(_ isActive: Bool) {
    	if isActive {
		//버튼 활성화
        } else {
		//버튼 비활성화
	}
    }
    
    // 생략...
}

사용할 버튼 하나를 생성했습니다. isActive라는 함수에 Bool타입 파라미터를 넘겨주면 값에 따라 버튼을 활성화/비활성화 시킵니다.

이제 ViewModel에서 어떤 성공여부를 버튼에 바인딩해서 버튼을 활성화/비활성화 시키려고 합니다. Binder함수가 구현되지 않은 경우 예시를 확인해보겠습니다.

let button = Button()

viewModel.output.isSuccess
	.subscribe(onNext: { [weak self] isSuccess in
		self.button.active(isSuccess)
	}
	.disposed(by: disposeBag)

output을 구독하는 부분에서 결과값에 따라 함수를 실행해야합니다. 하지만 저희는 Button에 Binder를 만들어 보다 간결하게 바인딩이 가능합니다.

Binder 구현

extension Reactive where Base: Button {
    public var isActive: Binder<Bool> {
        Binder(base) { base, newProperty in
            base.active(newProperty)
        }
    }
}

Binder는 Reactive 모듈에 구현돼 있으므로 Reactive를 extension합니다. 이때 where절을 활용해 내가 만든 Button에만 적용시킵니다.

Binder를 정의합니다. 이때 변수명은 button.rx.~ 물결부분에 해당합니다. 타입은 Binder<바인딩 하고자하는 타입>으로 설정해줍니다.

이제 클로져 내부를 구현할 차례입니다. 먼저 Binder문서를 확인해보겠습니다.

Value는 저희가 처음 설정했던 Bool타입이고 생성자 매개변수로 target이 들어가는데 target은 저희가 만든 컴포넌트입니다. 마지막으로 target, value를 매개변수로 갖고 이벤트 발생 시 실행될 클로져를 정의해줍니다.

target은 base, value는 새로 바인딩 되는 값이니 base.active(newProperty)로 새로운 이벤트가 발생했을때 값에 따라 active함수가 실행되도록 구현해줍니다.

전 후 비교

// before
viewModel.output.isSuccess
	.subscribe(onNext: { [weak self] isSuccess in
		self.button.active(isSuccess)
	}
	.disposed(by: disposeBag)

// after
viewModel.output.isSuccess
	.bind(to: button.rx.isActive)
	.disposed(by: disposeBag)

Binding을 추가해 보다 간결하게 바인딩로직이 리팩토링 됐습니다. 여러분들도 CustomView에 바인딩 프로퍼티를 한번 추가해보세요!

복사했습니다!