Расширение методов целевого действия с помощью RxSwift - PullRequest
0 голосов
/ 21 ноября 2018
class A{

     func addTarget(target: Any, action: Selector)
}

Допустим, у меня нет источника класса A (фреймворк).Как бы я расширил этот класс реактивно для передачи событий Rx через Observable?

Я могу создать класс, который просто перенаправляет события через PublishSubject, но в этом случае я бы не создавал расширение Reactive, а делал быэто через прокси класс.

let a = A()
let del = CustomClassThatAddsItselfAsATarget(a)
del.event.subscribe( ...

вместо

let a = A()
a.rx.event.subscribe( ...

Ответы [ 2 ]

0 голосов
/ 22 ноября 2018

Это было забавное исследование.Ниже показано, как UIControl настроен в RxCocoa.

В ответ на ваши вопросы:

Какой объект будет добавлен в качестве цели (метод addTarget) к базе?

Вы должны создать класс, предназначенный для этого.Я назвал его ATarget.

Кто удерживает этот объект?

Вы заставляете объект соответствовать Disposable и затем он будет сохраняться до уничтожения.

extension Reactive where Base: A {

    var event: Observable<A> {
        return Observable.create { [weak a = self.base] observer in
            guard let a = a else {
                observer.on(.completed)
                return Disposables.create()
            }

            let aTarget = ATarget(a: a, callback: { a in
                observer.on(.next(a))
            })

            return Disposables.create(with: aTarget.dispose)
        }
        .takeUntil(deallocated)
    }
}

class ATarget: NSObject, Disposable {

    typealias Callback = (A) -> Void
    let selector: Selector = #selector(ATarget.eventHandler)
    weak var a: A?
    var callback: Callback?

    init(a: A, callback: @escaping Callback) {
        self.a = a
        self.callback = callback
        super.init()
        a.addTarget(target: self, action: selector)
    }

    @objc func eventHandler() {
        if let callback = self.callback, let a = self.a {
            callback(a)
        }
    }

    func dispose() {
        self.a?.removeTarget(target: self)
        self.callback = nil
    }

}
0 голосов
/ 21 ноября 2018

RxCocoa и большинство других RxSwift основанных структур используют следующий подход -

public extension Reactive where Base: TheOriginalClass {

См. CKRecord + Rx или Bundle+ Rx для примера реализации.

Ситуация усложняется, если вам необходимо предоставить прокси-делегат, но это выходит за рамки этого вопроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...