NSObject添加disposeBag擴(kuò)展

溫馨提示:
本文純屬代碼潔癖患者搞事情!

本文關(guān)鍵字:

AssociatedObject RxSwift

對(duì)于NSObjectRxSwiftdisposeBag的擴(kuò)展,已有解決方案,就是NSObject+Rx。那么為什么還需要重復(fù)造車輪子呢?

為解決自定義UITableViewCellUICollectionViewCell 復(fù)用導(dǎo)致的button.rx.tap 重復(fù)訂閱問題,通常情況下,我們需要這樣做:

var disposeBag = DisposeBag()

override func prepareForReuse() {
    super.prepareForReuse()
    // Reallocate dispose bag to avoid multi subscribers
    self.disposeBag = DisposeBag()
}

而使用NSObject+Rx,我們只需要self.rx.disposeBag 即可自動(dòng)且優(yōu)雅的創(chuàng)建disposeBag 。然而,self.rx.disposeBag = DisposeBag() 會(huì)導(dǎo)致Xcode報(bào)錯(cuò):

Cannot assign to property: 'self' is immutable

我們先來看一下NSObject+Rx的源碼:

public extension Reactive where Base: AnyObject {

    /// a unique DisposeBag that is related to the Reactive.Base instance only for Reference type
    public var disposeBag: DisposeBag {
        get {
            return synchronizedBag {
                if let disposeObject = objc_getAssociatedObject(base, &disposeBagContext) as? DisposeBag {
                    return disposeObject
                }
                let disposeObject = DisposeBag()
                objc_setAssociatedObject(base, &disposeBagContext, disposeObject, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
                return disposeObject
            }
        }
        
        set {
            synchronizedBag {
                objc_setAssociatedObject(base, &disposeBagContext, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        }
    }
}

進(jìn)而,我們看一下RxSwift的源碼:

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
    }
}

注意到base的聲明了嗎?沒錯(cuò),是let

這樣一來,想要優(yōu)雅地為rx添加一個(gè)disposeBag是辦不到了,只能退而求其次,為類本身添加一個(gè)rx_disposeBag屬性:

/// AssociatedKeys
private struct AssociatedKeys {
    static var disposeBag = "disposeBag"
}

/// Synchronizing
/// - Parameter action: Closure
/// - Returns: Action result
func synchronized<T>(_ action: () -> T) -> T {
    objc_sync_enter(self)
    let result = action()
    objc_sync_exit(self)
    return result
}

/// Stored disposeBag
public var rx_disposeBag: DisposeBag {
    get {
        self.synchronized {
            if let disposeBag = objc_getAssociatedObject(self, &AssociatedKeys.disposeBag) as? DisposeBag {
                return disposeBag
            }
            let disposeBag = DisposeBag()
            objc_setAssociatedObject(self, &AssociatedKeys.disposeBag, disposeBag, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            return disposeBag
        }
    }
    set {
        self.synchronized {
            objc_setAssociatedObject(self, &AssociatedKeys.disposeBag, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}

這里還有另外一種方法,依舊使用NSObject+Rx擴(kuò)展,避免重復(fù)造車輪子:

override func prepareForReuse() {
    super.prepareForReuse()
    // Reallocate dispose bag to avoid multi subscribers
    var mutableSelf = self
    mutableSelf.rx.disposeBag = DisposeBag()
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容