๐Ÿ“Œ Language/Swift

[RxCocoa] bind๋ž€?

Fomagran ๐Ÿ’ป 2021. 7. 5. 12:34
320x100
๋ฐ˜์‘ํ˜•

์•ˆ๋…•ํ•˜์„ธ์š” Foma ๐Ÿ‘Ÿ ์ž…๋‹ˆ๋‹ค!

 

์˜ค๋žœ๋งŒ์— Rx๊ด€๋ จ ํฌ์ŠคํŒ…์„ ํ•˜๋„ค์š”.

 

์˜ค๋Š˜์€ UI ํŠนํ™”๋œ Operator ์ค‘ bind์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

๋ฐ”๋กœ ์‹œ์ž‘ํ• ๊ฒŒ์š”~


Binder 

 

๋จผ์ € bind๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„  Binder๋ฅผ ์•Œ์•„์•ผ ํ•˜๋Š”๋ฐ์š”.

 

Binder๋Š” ์˜ต์ €๋ฒ„ ํƒ€์ž…์œผ๋กœ 3๊ฐ€์ง€ ํŠน์ง•์ด ์žˆ๋Š”๋ฐ์š”.

 

์ฒซ ๋ฒˆ์งธ๋กœ๋Š” ๋ฐ˜๋“œ์‹œ ๋ฉ”์ธ์Šค์ผ€์ฅด๋Ÿฌ์—์„œ ์‹คํ–‰๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

๋‘ ๋ฒˆ์งธ๋กœ๋Š” ์—๋Ÿฌ ์ด๋ฒคํŠธ๋ฅผ ๋”ฐ๋กœ ๋ฐฉ์ถœํ•˜์ง€ ์•Š๊ณ  ๋กœ๊ทธ๋กœ๋งŒ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.

 

์„ธ ๋ฒˆ์งธ๋กœ๋Š” ์˜ต์ €๋ฒ„ํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ์— ์ƒˆ๋กœ์šด ๊ฐ’์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ตฌ๋…์ž๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

 

public struct Binder<Value>: ObserverType {
    public typealias Element = Value
    
    private let binding: (Event<Value>) -> Void

    /// Initializes `Binder`
    ///
    /// - parameter target: Target object.
    /// - parameter scheduler: Scheduler used to bind the events.
    /// - parameter binding: Binding logic.
    public init<Target: AnyObject>(_ target: Target, scheduler: ImmediateSchedulerType = MainScheduler(), binding: @escaping (Target, Value) -> Void) {
        weak var weakTarget = target

        self.binding = { event in
            switch event {
            case .next(let element):
                _ = scheduler.schedule(element) { element in
                    if let target = weakTarget {
                        binding(target, element)
                    }
                    return Disposables.create()
                }
            case .error(let error):
                rxFatalErrorInDebug("Binding error: \(error)")
            case .completed:
                break
            }
        }
    }

bind๋ž€? 

 

Binder ์˜ต์ €๋ฒ„๋ฅผ ์‚ฌ์šฉํ•ด์„œ UI์™€ ์˜ต์ €๋ฒ„๋ธ”์„ ํ•˜๋‚˜๋กœ ๋ฌถ๋Š” ํ–‰์œ„์ž…๋‹ˆ๋‹ค.

 

์‰ฝ๊ฒŒ ์„ค๋ช…ํ•˜๋ฉด Observable์ด ์ด๋ฒคํŠธ๋ฅผ ๋ฐฉ์ถœํ•˜๊ณ  subscribe๋ฅผ ํ†ตํ•ด ๊ด€์ฐฐ์„ ํ–ˆ์ฃ ?

 

bind๋Š” ์˜ต์ €๋ฒ„๋ธ”๊ณผ ๊ด€์ฐฐํ•˜๋Š” ์˜ต์ €๋ฒ„๋ฅผ ๊ทธ๋ƒฅ ํ•˜๋‚˜๋กœ ๋ฌถ์–ด๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์ด์ฃ .

 

๋งŒ์•ฝ ๋ ˆ์ด๋ธ”์˜ ํ…์ŠคํŠธ๋ฅผ ์˜ต์ €๋ฒ„๋ธ”์ด ๋ฐฉ์ถœํ•œ ์ด๋ฒคํŠธ๋Œ€๋กœ ๋ฐ”๊พธ๊ณ ์‹ถ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 observable.subscribe{
	self.label.text = $0
	}.disposed(by: disposeBag)

 

ํ•˜์ง€๋งŒ bind๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฐฉ์ถœํ•œ ์ด๋ฒคํŠธ ๊ทธ๋Œ€๋กœ๋ฅผ label์˜ ํ…์ŠคํŠธ์™€ bind ํ•ด์ค˜๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์ด์ฃ !

 

(bind๋Š” ๊ฐ’์„ ์ „๋‹ฌํ•˜๊ธฐ๋งŒ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ด€์ฐฐ์„ ํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.)

 

observable
	.bind(to: label.rx.text)
	.disposed(by: disposeBag)

 

bind ๋‚ด๋ถ€ ์ฝ”๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด subscribe๋ฅผ ํ†ตํ•ด์„œ ์ด๋ฒคํŠธ๋ฅผ ๊ด€์ฐฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

public func bind<Observer: ObserverType>(to observers: Observer...) -> Disposable where Observer.Element == Element {
        self.subscribe { event in
            observers.forEach { $0.on(event) }
        }
    }

 

๋งŒ์•ฝ ์—๋Ÿฌ๊ฐ€ ์ƒ๊ฒผ๋‹ค๋ฉด bind๋Š” ์—๋Ÿฌ๋ฅผ ๋ฐฉ์ถœํ•˜์ง€ ์•Š๊ณ  ๋กœ๊ทธ๋กœ ์ถœ๋ ฅํ•ด์ค๋‹ˆ๋‹ค.

 

public func bind(onNext: @escaping (Element) -> Void) -> Disposable {
        self.subscribe(onNext: onNext,
                       onError: { error in
                        rxFatalErrorInDebug("Binding error: \(error)")
                       })
    }

 

UIButton๊ณผ title์„ rx๋กœ ๋ฐ”์ธ๋”ฉํ•  ๋•Œ ์‹ค์ œ๋กœ Binder๋ฅผ returnํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

extension Reactive where Base: UIButton {
    /// Reactive wrapper for `setTitle(_:for:)`
    public func title(for controlState: UIControl.State = []) -> Binder<String?> {
        Binder(self.base) { button, title in
            button.setTitle(title, for: controlState)
        }
    }

์ •๋ฆฌ

 

bind๋Š” UI์™€ ์˜ต์ €๋ฒ„๋ธ”์„ ๋ฌถ๋Š” ํ–‰์œ„๋กœ ๊ฐ’์„ ์ „๋‹ฌํ•˜๊ธฐ๋งŒ ํ•˜๋ฉฐ ๋ฉ”์ธ ์“ฐ๋ ˆ๋“œ์—์„œ ์ž‘๋™ํ•˜๊ณ  ์—๋Ÿฌ๋ฅผ ๋ฐฉ์ถœํ•˜์ง€๋„ ์•Š๋Š”๋‹ค.

320x100
๋ฐ˜์‘ํ˜•