Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- 리팩토링
- HIG
- 애니메이션
- Refactoring
- tableView
- map
- rxswift
- 리펙토링
- swiftUI
- 클린 코드
- combine
- uiscrollview
- clean architecture
- UITextView
- Observable
- MVVM
- Human interface guide
- Xcode
- RxCocoa
- Protocol
- SWIFT
- 스위프트
- Clean Code
- 리펙터링
- ios
- UICollectionView
- uitableview
- swift documentation
- ribs
- collectionview
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - Swift] (RxSwift) ControlEvent, ControlProperty, Binder 이해하기 (#Reactive Extension) 본문
iOS 응용 (swift)
[iOS - Swift] (RxSwift) ControlEvent, ControlProperty, Binder 이해하기 (#Reactive Extension)
jake-kim 2022. 11. 6. 22:47Reactive Extension
- Reactive란?
- base를 초기화로 넘겨주면, 내부에서 base property를 들고있는 상태
@dynamicMemberLookup
public struct Reactive<Base> {
public let base: Base
public init(_ base: Base) {
self.base = base
}
public subscript<Property>(dynamicMember keyPath: ReferenceWritableKeyPath<Base, Property>) -> Binder<Property> where Base: AnyObject {
Binder(self.base) { base, value in
base[keyPath: keyPath] = value
}
}
}
- Reactive Extension
- extension으로 Base 타입을 정해주고, 구현해주면 사용하는쪽에서 button.rx.tap으로 접근이 가능
- base.rx.tap
// UIButton+Rx
extension Reactive where Base: UIButton {
public var tap: ControlEvent<Void> {
controlEvent(.touchUpInside)
}
}
- 위에서 나오는 controlEvent는?
- UIControl.event를 wrapping한 형태 (ControlEvent는 Observable타입 중 하나)
extension Reactive where Base: UIControl {
public func controlEvent(_ controlEvents: UIControl.Event) -> ControlEvent<()> {
let source: Observable<Void> = Observable.create { [weak control = self.base] observer in
MainScheduler.ensureRunningOnMainThread()
guard let control = control else {
observer.on(.completed)
return Disposables.create()
}
let controlTarget = ControlTarget(control: control, controlEvents: controlEvents) { _ in
observer.on(.next(()))
}
return Disposables.create(with: controlTarget.dispose)
}
.take(until: deallocated)
return ControlEvent(events: source)
}
}
ControlEvent, ControlProperty, Binder 차이
- Observer 타입은 값을 관찰 못하고 방출만 할 수 있고, Observable 타입은 값을 관찰만 할 수 있는데 이와 유사한 기능을 나누어 놓은 것
- Observer와 Observable로 표현할 수 있지만 굳이 새로 만들어서 사용하는 이유?
- RxCocoa의 Traits에서 제공하는 프로퍼티
- Traits이 UI만을 처리하기 위한 프로퍼티이므로 MainScheduler에서 실행
- UI을 처리하기 위한 개념이므로 error와 fail 이벤트가 존재하지 않음 (단 메모리 해제시 complete 이벤트는 방출)
- 차이
- ControlEvent: `이벤트` (값 관찰만 가능)
- ControlProperty: `프로퍼티` (값 관찰, 방출 모두 가능)
- Binder: `다른 `
ControlEvent | ControlProperty | Binder | |
읽기 (값 관찰) | O | O | X |
쓰기 (값 방출) | X | O | O |
ex) ControlEvent
- 읽기만 가능
// button.rx.tap 정의
extension Reactive where Base: UIButton {
public var tap: ControlEvent<Void> {
controlEvent(.touchUpInside)
}
}
// 사용하는쪽 - 읽기만 가능
button.rx.tap
.observe(on: MainScheduler.asyncInstance)
.bind(with: self) { ss, _ in
print("Tap!")
}
.disposed(by: disposeBag)
ex) ControlProperty
- 읽기, 쓰기 가능
// textField.rx.text 정의
extension Reactive where Base: UITextField {
public var text: ControlProperty<String?> {
value
}
}
// 사용1 - 쓰기
Observable.just(())
.observe(on: MainScheduler.asyncInstance)
.bind(to: textField.rx.text)
.disposed(by: disposeBag)
// 사용2 - 읽기
textField.rx.text
.observe(on: MainScheduler.asyncInstance)
.bind(with: self) { ss, _ in
print(text)
}
.disposed(by: disposeBag)
ex) Binder
- 쓰기만 가능
- UITextField에 Date 값을 입력하면 포멧에 맞추어서 text에 set 되는 기능
- Base는 set할 타입을 명시하고, Binder의 제네릭 타입에 주입할 타입을 명시
// 정의
extension Reactive where Base: UITextField {
var formattedText: Binder<Date> {
Binder(self.base) { textField, date in
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "YYYY년 MM월 dd일 HH:mm"
textField.text = dateFormatter.string(from: date)
}
}
}
// 사용하는쪽 - 쓰기
Observable.just(())
.map { Date() }
.bind(to: textField.rx.formattedText)
.disposed(by: disposeBag)
'iOS 응용 (swift)' 카테고리의 다른 글
Comments