티스토리 뷰
안녕하세요 :) Zedd입니다.
저는 막 Reactive를 extension하여 써본적이 없는데...굉장히 일반적이고 많이 사용되는 방법 같더라구요~
공부해보려고 합니다!
# Reactive
RxSwift를 보면, Reactive.swift파일이 있습니다.
constrained protocol extensions을 위한 custom point로 'Reactive'를 사용하라고 하는데요.
public struct Reactive<Base> {
/// Base object to extend.
public let base: Base
/// Creates extensions with base object.
///
/// - parameter base: Base object.
public init(_ base: Base) {
self.base = base
}
}
일반적인 패턴은 다음과 같습니다.
1. Reactive를 extension하고 Base에 대한 constrain(제한)을 건다
extension Reactive where Base: SomeType { }
이런식
2. extension안에 SomeType에 대한 특정 reactive extension을 구현한다.
# Example1 - ControlEvent
아주 간단한 예를 들어보자. button의 탭을 감지하고 싶다.
self.myButton.rx
.controlEvent(.touchUpInside)
.bind {
print("button tapped!")
}
.disposed(by: self.disposeBag)
이렇게 직접 controlEvent를 호출하여 tap을 감지할 수도 있지만,
UIButton쪽에서는
self.myButton.rx
.tap
.bind {
print("button tapped!")
}
.disposed(by: self.disposeBag)
tap이라는 프로퍼티가 이미 있다.
이는
// UIButton + Rx
extension Reactive where Base: UIButton {
/// Reactive wrapper for `TouchUpInside` control event.
public var tap: ControlEvent<Void> {
controlEvent(.touchUpInside)
}
}
이렇게 Reactive를 extension하여 tap이라는 프로퍼티를 구현해놓았기 때문.
ControlEvent - 값을 관찰 할 수는 있지만, 값을 주입시키지는 못한다.
# Example2 - ControlProperty
ControlProperty를 리턴시킬수도 있다.
ControlProperty - 값을 주입시킬수도 있고, 값의 변화도 관찰 할 수 있는 타입
예를들어 UITextField의 text는 ControlProperty이다.
extension Reactive where Base: UITextField {
/// Reactive wrapper for `text` property.
public var text: ControlProperty<String?> {
value
}
}
값을 주입시킬수도 있고, 값의 변화도 관찰할 수 있게 만들고 싶다면 위와같이 Reactive를 extension하면 된다.
1. 값 주입이 가능하기 때문에
textField.rx.text.onNext("안녕")
2. 값을 관찰 할 수 있기 때문에
textField.rx.text.subscribe(onNext: { _ in })
이런것이 가능.
# Example 3 - Binder
Binder를 리턴시킬수도 있다.
Binder - 값을 주입시킬수는 있지만, 값을 관찰하는 것은 불가능
예를들어 UILabel의 text는 Binder이다.
Binder. 즉 관찰하는 것이 불가능 하므로 subscribe 호출 불가.
이미 UIButton+Rx에 있지만;;; UIButton에 setImage를 하고 싶다고 하자.
setImage는 관찰할 수 있게 하기 보다는 값을 주입시키는 역할이다.
그러므로 Binder로 정의하는 것이 맞음.
myButton.rx~ 이런 플로우로 setImage할 방법이 없을 때
extension Reactive를 사용하면 된다.
extension Reactive where Base: UIButton {
public func zeddCustomImage() -> Binder<UIImage?> {
}
}
이렇게 Binder를 리턴하도록 만들어준다. (image값을 주입시켜줄거니까 UIImage타입을 넣어줌)
Binder를 리턴해야하니까 Binder를 만들어주면 되는데,
Binder의 원형(?)은 이렇게 생겼다.
Target이 있고, binding쪽에는 Target과 넘겨줄 value 파라미터를 넣어주면 된다.
extension Reactive where Base: UIButton {
public func zeddCustomImage() -> Binder<UIImage?> {
return Binder(self.base) { (button, image) in
button.setImage(image, for: [])
}
}
}
이런식.
self.myButton.rx
.zeddCustomImage()
.onNext(UIImage(systemName: "heart"))
그래서 이렇게 해주면
이런식으로 setImage를 할 수 있다.
물론 이 메소드는 UIButton+Rx쪽에 image()로 잘 구현이 되어있다;
# 참고. ControlEvent와 ControlProperty 공통점, 차이점
공통점
- RxCocoa Traits종류
- MainScheduler에서 실행 (애초에 Traits이 UI처리를 위한 Observable이니 당연)
- 절대 실패 X, 에러 X (이것도 당연)
- control이 dealloc되면 Complete 이벤트 방출
차이점
[ControlProperty]
- share(replay: 1) behavior
[ControlEvent]
- 구독시 초기값 보내지 않음.
혹시 틀린 부분이 있다면 댓글 부탁드립니다!
참고
github.com/ReactiveX/RxSwift/blob/main/Documentation/Traits.md#controlproperty--controlevent
'공부' 카테고리의 다른 글
앱 종료하기 with animation (2) | 2021.05.04 |
---|---|
FlexLayout 사용해보기 (4) | 2021.05.02 |
PinLayout 사용해보기 (0) | 2021.04.21 |
Carthage 사용해보기 (0) | 2021.04.17 |
Carthage (0) | 2021.04.15 |
- github
- Swift
- FLUTTER
- SwiftUI
- WidgetKit
- Combine
- Git
- IOS
- swift sort
- fastlane
- 회고
- actor
- ios 13
- UIBezierPath
- np-hard
- 피아노
- 스위프트 문법
- WKWebView
- swift array
- swift delegate
- 스위프트
- swift3
- Xcode
- WWDC
- Accessibility
- swift tutorial
- swift 공부
- np-complete
- iOS delegate
- 제이슨 파싱
- Total
- Today
- Yesterday