-
Notifications
You must be signed in to change notification settings - Fork 4
Reactive
在使用 RxSwift
时,我们经常会书写如下代码:
万物.rx.xxx
在使用过 SnapKit
、KingFisher
等优秀的开源库时,已感受到这种代码实现的魅力,但当时只是觉得这种命名空间的形式很新鲜,最明显的感受就是接口隔离,避免了 Object-C 那种臃肿的类前缀、方法前缀的写法(比如早期 AFN 与 SDWebImage 命名冲突),而再次在 RxSwift
遇到这种写法时,不再局限于设置布局、设置图片,而是适用于万物,感受到了 RxSwift
强大的同时,被这种代码实现方式所吸引,是时候深刻学习研究一下了
-
Reactive.swift
完整源码 (RxSwift 6.5
)/** Use `Reactive` proxy as customization point for constrained protocol extensions. General pattern would be: // 1. Extend Reactive protocol with constrain on Base // Read as: Reactive Extension where Base is a SomeType extension Reactive where Base: SomeType { // 2. Put any specific reactive extension for SomeType here } With this approach we can have more specialized methods and properties using `Base` and not just specialized on common base type. `Binder`s are also automatically synthesized using `@dynamicMemberLookup` for writable reference properties of the reactive base. */ @dynamicMemberLookup 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 } /// Automatically synthesized binder for a key path between the reactive /// base and one of its properties public subscript<Property>(dynamicMember keyPath: ReferenceWritableKeyPath<Base, Property>) -> Binder<Property> where Base: AnyObject { Binder(self.base) { base, value in base[keyPath: keyPath] = value } } } /// A type that has reactive extensions. public protocol ReactiveCompatible { /// Extended type associatedtype ReactiveBase /// Reactive extensions. static var rx: Reactive<ReactiveBase>.Type { get set } /// Reactive extensions. var rx: Reactive<ReactiveBase> { get set } } extension ReactiveCompatible { /// Reactive extensions. public static var rx: Reactive<Self>.Type { get { Reactive<Self>.self } // this enables using Reactive to "mutate" base type // swiftlint:disable:next unused_setter_value set { } } /// Reactive extensions. public var rx: Reactive<Self> { get { Reactive(self) } // this enables using Reactive to "mutate" base object // swiftlint:disable:next unused_setter_value set { } } } import Foundation /// Extend NSObject with `rx` proxy. extension NSObject: ReactiveCompatible { }
在 Reactive.swift
中可以分为三部分
-
struct Reactive
- 结构体
Reactive
包含一个成员base
, 也就是我们包装的实例对象,其类型通过泛型管理 -
subscript
方法是配合@dynamicMemberLookup
所实现的
- 结构体
-
protocol ReactiveCompatible
- 协议
ReactiveCompatible
为遵循者提供了Reactive
结构体类型rx
属性: 一个静态的,一个实例的,使用到了关联类型 - 通过
extension
给出rx
属性默认实现- 实例:直接实例化一个
Reactive<实例对象类型>
结构体实例,而结构内包装的base
成员就是遵循ReactiveCompatible
协议的实例对象 - 静态:不需要实例化,直接就是一个类型包装
- 实例:直接实例化一个
- 协议
-
extension NSObject
- 给
NSObject
默认遵循了ReactiveCompatible
,提供了rx
的扩展, 这样能默认覆盖绝大多数类
- 给
对比 RxSwift 5.0
最大的改变就是支持了动态成员查找 @dynamicMemberLookup
在查阅资料时,看到了这个关闭状态的 issuse
: ReactiveCompatible is a class protocol in RxSwift 6
Reactive.swift (RxSwift 5.0)
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
}
}
/// A type that has reactive extensions.
public protocol ReactiveCompatible {
/// Extended type
associatedtype ReactiveBase
@available(*, deprecated, renamed: "ReactiveBase")
typealias CompatibleType = ReactiveBase
/// Reactive extensions.
static var rx: Reactive<ReactiveBase>.Type { get set }
/// Reactive extensions.
var rx: Reactive<ReactiveBase> { get set }
}
extension ReactiveCompatible {
/// Reactive extensions.
public static var rx: Reactive<Self>.Type {
get {
return Reactive<Self>.self
}
// swiftlint:disable:next unused_setter_value
set {
// this enables using Reactive to "mutate" base type
}
}
/// Reactive extensions.
public var rx: Reactive<Self> {
get {
return Reactive(self)
}
// swiftlint:disable:next unused_setter_value
set {
// this enables using Reactive to "mutate" base object
}
}
}
import class Foundation.NSObject
/// Extend NSObject with `rx` proxy.
extension NSObject: ReactiveCompatible { }
结合我自身的情况
第一次使用 RxSwift
时,使用的就是 5.0
这个版本,在第二个项目中升级到了 6.2
, 但是我似乎并没有感觉到什么异样
看标题的确是挺吓人,Swift
中的三大金刚: class
、struct
、enum
都是允许遵循协议使用的,苹果官方也是尽可能的建议我们使用 struct
替代 class
,如果像标题描述的那样,那的确是个不小的事
这条 issuse
讨论的信息不多,很快就可以读完,得到的信息是:
在
RxSwift 6.0
上,的确带来了这个副作用 (为了增添动态查找属性的能力,而限定了协议的使用范围),但很快就在RxSwift 6.1
版本修复了这个问题
Reactive now supports structs and value-types again, with the dynamic look-up specifically dealing with AnyObjects #2285
ShenYj.github.io - 简书地址 - 返回首页
-
Apple
Common
蓝牙
LBS
音视频
- AVAudioSessionchange_route
- 切换线路
- StreamingKit
- Audio Unit 基础
OC 与 Swift 混编
Object-C
- 代码混淆
- autoreleasepool
- 忽略编译器(clang)警告
- 定时器
- 锁
- RunLoop
- block
- NS_REFINED_FOR_SWIFT
- NS_CLOSED_ENUM
- NS_TYPED_ENUM、NS_STRING_ENUM
- NS_TYPED_EXTENSIBLE_ENUM、NS_EXTENSIBLE_STRING_ENUM
- 关键字nonnull和nullable
- class、objc_getClass和object_getclass方法区别
- isKindOfClass和isMemberOfClass
- 应用程序的加载
- non-lazy classes & lazy classes
- load方法
- initialize方法
- 方法的本质
- 类型编码
- self和super
- 类的内存分析
Swift
- precondition
- 权限控制
- Array常用Api
- String初始化、定义
- String常用Api
- String截取演练
- Set定义、创建
- Set访问和修改
- Dictionary操作
- Dictionary和KeyValuePairs
- Dictionary与String转换
- 常用高阶函数
- enum原始值
- enum关联值
- enum遍历
- 递归enum
- enum内存分配
- 指针
- for循环
- break跳出循环
- 变量名与关键字冲突
- 类的定义
- 类的继承和初始化
- 关键字: final
- 关键字: mutating
- 关键字: lazy
- 修饰类方法的关键字: static
- 关键字: final、dynamic、objc和_dynamicReplacement
- 关键字:@dynamicMemberLookup和@dynamicCallable
- 关键字: propertyWrapper
- 自定义运算符
- 下标: subscript
- 扩展: extension
- 协议: protocol
- 协议和扩展
- 为什么需要泛型
- 泛型函数定义
- 泛型类型
- 泛型的类型约束
- 关联类型
- 为泛型定义要求
- 泛型下标
- 多线程
- Attributes
- 错误处理
- Codable
- DispatchSourceTimer
- Swift 5.x 演练: 更多功能编辑页
- Swift 5.x 类库收集
- 单元测试笔记
- 实例对象内存结构
- 元类型、Type、Self
- frozen
- convention
- Swift(5.3.2)源码编译
- SQLite.Swift类库演练
- Swift 5.5 关键字: async/await
- Swift 5.5 新特性: Continuations
- Swift 5.5 新特性: Actor
- Swift 方法调度
- Swift Mirror
- Swift 关键字: @_silgen_name
- Swift 关键字: @_disfavoredOverload
- swiftmodule
- Swift 5.6 新特性: Type placeholders
- Swift 5.6 新特性: #unavailable
- Swift 5.6 新特性: CodingKeyRepresentable
- Swift 5.6 新特性: existential any
- Swift 5.7 新特性: if-let/guard 语法简化
- Swift 5.7 新特性: Multi-statement closure type inference
- Swift 5.8 新特性: @backDeployed
- Swift 5.9 新特性: if switch expressions
- Swift 6.0 新特性:@preconcurrency
RxSwift
macOS - AppKit
-
iOS Assembly(ARM64)
-
C++
C++ 基础
- cout、cin
- 函数重载
- 默认参数
- extern "C"
- pragma once
- inline function
- const
- Reference
- 汇编
- 类和对象
- 堆空间内存管理
- Constructor
- Destructor
- 成员变量初始化
- 声明与实现分离
- namespace
- 继承
- 访问权限
- 初始化列表
- 多态:虚函数
- 多态:虚函数实现原理
- 多态:虚析构函数
- 多态:纯虚函数
- 多态:抽象类
- 多继承
- static
- static: 单例模式
- const 成员
- 引用类型成员
- 拷贝构造函数
- 调用父类的拷贝构造函数
- 浅拷贝、深拷贝
- 对象型参数和返回值
- 匿名对象
- 隐式构造
- 编译器自动生成的构造函数
- 友元
- 内部类
- 局部类
- 运算符重载
- 模板
- 类型转换
- C++标准
- Lambda
- 异常
- 智能指针
-
Flutter
Dart
Flutter
-
Go
Go 基础
-
Ruby
Ruby 基础
-
React-Native
React-Native
-
工具篇
-
Swift Package Manager
-
自动化
-
TroubleShooting
-
扩展