十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

从零手写 NSObject-Rx:用 Objective-C Runtime 实现自己的 rx.disposeBag 完整教程

从零手写 NSObject-Rx:用 Objective-C Runtime 实现自己的 rx.disposeBag 完整教程 从零手写 NSObject-Rx用 Objective-C Runtime 实现自己的 rx.disposeBag 完整教程【免费下载链接】NSObject-RxHandy RxSwift extensions on NSObject, including rx.disposeBag.项目地址: https://gitcode.com/gh_mirrors/ns/NSObject-Rx在 RxSwift 开发中rx.disposeBag几乎是每个 iOS 工程师的标配它帮你管理订阅生命周期在对象销毁时自动释放资源。可你是否好奇过这个看似神奇的能力其实只用了几十行代码本教程将带你从零手写一个 NSObject-Rx 风格的扩展用 Objective-C Runtime 的关联对象Associated Objects机制实现属于自己的rx.disposeBag。读完你不仅能彻底理解其原理还能在项目里轻松复用。为什么每个 RxSwift 项目都需要 disposeBag在响应式编程中Observable订阅后需要被持有否则订阅会立即失效。最朴素的做法是在每个类里写一行class MyViewController: UIViewController { let disposeBag DisposeBag() }这张截图正是 GitHub 上搜索let disposeBag DisposeBag()的结果——足足 489 条代码结果几乎遍布所有 Swift 仓库。代码重复意味着风险容易漏写、命名冲突还得操心销毁时机。理解核心原理Objective-C 关联对象NSObject-Rx 的精髓在于不需要给每个类新增存储属性也能挂一个属性上去。这靠的是 Objective-C Runtime 的关联对象 APIobjc_getAssociatedObject读取关联值objc_setAssociatedObject写入关联值NSObject的每个实例在 Runtime 层都有一张隐形字典关联对象就存在里面。当对象被释放时关联对象也会一并清理生命周期与宿主完全一致——这正是rx.disposeBag能自动释放的根本原因。从零手写 rx.disposeBag核心实现步骤整个库的核心代码只有两个文件NSObjectRx.swift和HasDisposeBag.swift。我们一步步来。第一步给 Reactive 扩展添加 disposeBag 属性RxSwift 的Reactive结构体是给类型挂 Rx 能力的入口。我们扩展它让任何NSObject子类都能用rx.disposeBagfileprivate var disposeBagContext: UInt8 0 public extension Reactive where Base: AnyObject { var disposeBag: DisposeBag { get { if let bag objc_getAssociatedObject(base, disposeBagContext) as? DisposeBag { return bag } let bag DisposeBag() objc_setAssociatedObject(base, disposeBagContext, bag, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) return bag } set { objc_setAssociatedObject(base, disposeBagContext, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } }关键点有两个disposeBagContext作为唯一的关联 key任意唯一地址即可.OBJC_ASSOCIATION_RETAIN_NONATOMIC表示强引用持有保证 bag 不被提前回收。第二步加锁避免线程竞争原版代码还藏着一个细节synchronizedBag方法用objc_sync_enter/exit包裹读写操作。因为disposeBag可能被多个线程同时访问加上同步锁才能保证线程安全。这也是手写时最容易遗漏、却最体现工程质量的部分。第三步用 HasDisposeBag 协议覆盖非 NSObject 类型并非所有对象都继承自NSObject比如纯 Swift 类。NSObject-Rx 提供了HasDisposeBag协议任何遵守它的类都能拿到默认的disposeBagpublic protocol HasDisposeBag: AnyObject { var disposeBag: DisposeBag { get set } }协议扩展里实现同样的关联对象逻辑一套代码两处复用设计非常优雅。完整代码在哪里想对照学习完整实现直接看这两个源文件NSObjectRx.swiftrx.disposeBag扩展 线程同步HasDisposeBag.swift面向非 NSObject 类型的协议实现配套的单元测试在 DemoTests.swift覆盖了三个核心场景setter 是否生效、对象释放后订阅是否自动取消、rx.disposeBag是否按预期销毁。一行代码接入安装与使用最快配置方法CocoaPods在Podfile中加入一行pod NSObjectRx支持 CocoaPods、CarthageCartfile和 Swift Package ManagerPackage.swift三种方式任选其一即可。使用效果告别手写属性thing .bind(to: otherThing) .disposed(by: rx.disposeBag)订阅绑定后当宿主对象 deinit 时DisposeBag自动 dispose所有订阅随之清理——无需手动调用dispose()无泄漏、无崩溃。手写 vs 现成库怎么选想学习原理、深度定制照着本教程手写掌握关联对象与线程安全两大核心几十行代码足够。想快速上生产直接引入 NSObject-Rx它经过了多年迭代与全平台iOS/macOS/watchOS/tvOS验证版本演进见 Changelog.md。写在最后 ✨从每个类写一行 disposeBag到一行代码自动管理NSObject-Rx 用 Objective-C Runtime 的关联对象给出了教科书级的答案。现在你已经知道它的全部秘密——不妨动手敲一遍把你自己的rx.disposeBag写出来跑通测试你会对 RxSwift 的订阅管理有全新的理解。需要源码对照时记得项目 Demo 里就有完整的测试用例可供参考哦【免费下载链接】NSObject-RxHandy RxSwift extensions on NSObject, including rx.disposeBag.项目地址: https://gitcode.com/gh_mirrors/ns/NSObject-Rx创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表