RxSwift 6 有哪些新特性?
祝大家2021年新年快乐!过去的一年非常艰难,我相信我们都希望新的一年会更好,我们最终能够恢复正常生活。
新年伊始,还有什么比发布新版本更好的呢? 让我们一起来认识一下 RxSwift 6 吧 !
这篇博文将为您简要概述一些可能影响您的最值得注意的变化。
注 :这只是部分有趣的更改列表,显然不包括大量的较小错误修复和改进。
完整的变更日志请查看 发行说明 。
事不宜迟,让我们直接进入正题吧!
目录
变化
新标志!
这当然不是一项技术性改动,但绝对值得一提。
RxSwift 一直使用 Reactive Extensions 的原始 Volta Eel 标志,但我认为这次重大版本更新是一个很好的机会,可以为 RxSwift 的标志增添一些独特的元素。
这是一个让它拥有独特精神和身份的机会,同时还能向最初的 ReactiveX 标志和 Swift 的标志致敬。
隆重推出 RxSwift 的全新标志!
Binder从 RxCocoa 迁移到 RxSwift
这是一个虽小但呼声很高的改动,而且确实很合理。 Binder顾名思义,它允许你定义一种将 Observable流绑定到其中的方法,以便响应式地向该绑定的输入提供数据。
例如:
viewModel . isButtonEnable . bind ( to : myButton . rx . isEnabled )
Enter fullscreen mode
Exit fullscreen mode
使用底层接口 Binder让你绑定到 rx.isEnabled
Binder它一直存在于内部 RxCocoa,但我们社区的用例和各种讨论表明,它是一个超级有用的实体,服务于更广泛的 RxSwift 用户,因此它现在是其中的一部分,并且不需要 RxCocoa 即可使用 Binder。
Binder使用 自动合成 @dynamicMemberLookup
RxSwift 包含一个名为 `ReactiveExtensions` 的命名空间 .rx,允许你为特定对象添加自己的响应式扩展。
例如,假设有一个 MyView如下所示的自定义设置:
class MyView : UIView {
var title : String
var subtitle : String ?
var icon : UIImage ?
}
Enter fullscreen mode
Exit fullscreen mode
创建响应式绑定器的常见模式通常如下所示:
extension Reactive where Base : MyView {
var title : Binder < String > {
Binder ( base ) { base , title in
base . title = title
}
}
var subtitle : Binder < String ? > {
Binder ( base ) { base , subtitle in
base . subtitle = subtitle
}
}
var icon : Binder < UIImage ? > {
Binder ( base ) { base , icon in
base . icon = icon
}
}
}
Enter fullscreen mode
Exit fullscreen mode
这样就可以将适当类型的可观察流绑定到各种响应式输入:
viewModel . title . bind ( to : myView . rx . title )
viewModel . subtitle . bind ( to : myView . rx . subtitle )
viewModel . icon . drive ( myView . rx . icon )
Enter fullscreen mode
Exit fullscreen mode
这种方法效果很好,RxCocoa 本身也是通过这种方式 为其用户提供反应性粘合剂的 。
不幸的是,这种代码也相当重复且冗余。它 实际上 只是镜像了底层对象 Base的属性。
幸运的是,自 Swift 5.1 以来,我们有了更好的解决方案来解决这个问题—— @dynamicMemberLookup。
RxSwift 6 会自动 为任何类 合成所有这些 Binder元素,这意味着我上面展示的所有 Binder代码都可以完全删除,从而真正地清理你的代码。
.rx只需在任何继承自该类的类上 开始编写代码 AnyObject,您就会立即看到为扩展基对象的每个属性自动合成的绑定器:
不过不用担心,您自定义的响应式扩展仍然优先于合成的动态成员扩展,这使您可以进行更精细的控制。
withUnretained来到 RxSwift
在使用 RxSwift 和 Cocoa/iOS 代码时,一种常见的模式是获取弱引用, self以便将发出的值传递给所有者,例如:
viewModel . importantInfo
. subscribe ( onNext : { [ weak self ] info in
guard let self = self else { return }
self . doImportantTask ( with : info )
})
. disposed ( on : disposeBag )
Enter fullscreen mode
Exit fullscreen mode
注意 :使用此操作符时,请谨慎使用缓冲操作符,因为 share(replay: 1)它也会缓冲被保留的对象,这可能会导致循环引用。如果您需要更简单的替代方案,请查看 subscribe(with:onNext:onError:onCompleted:onDisposed:)RxSwift 6.1 及更高版本 。
对于单个输出来说,这似乎没什么问题,但想象一下,在单个代码库中,这种情况会频繁出现。
幸运的是, RxSwiftExt (一个包含各种RxSwift本身不包含的额外运算符的社区项目)有一个专门用于这种情况的运算符,名为` withUnretained.`。它 最初 是由我的好朋友兼iOS演讲者 Vincent Pradeilles 实现的。
由于该运算符的流行程度以及这种用例的普遍性,将其引入 RxSwift 本身就很有意义。
从 RxSwift 6 开始,你可以像这样重写上面的代码:
viewModel . importantInfo
. withUnretained ( self ) // Tuple of (Object, Element)
. subscribe ( onNext : { owner , info in
owner . doImportantTask ( with : info )
})
. disposed ( by : disposeBag )
Enter fullscreen mode
Exit fullscreen mode
干净多了!
Infallible
Infallible是一种新型流,它与普通流完全相同, Observable只有一个区别——它保证不会失败。这意味着编译器保证你无法从中发出错误。
例如,你可以 Observable.create使用以下方法创建一个类似的对象 Infallible.create:
Infallible < String >. create { observer in
observer ( . next ( "Hello" ))
observer ( . next ( "World" ))
observer ( . completed )
// No way to error here
return Disposables . create {
// Clean-up
}
}
Enter fullscreen mode
Exit fullscreen mode
请注意,您只能传递 `a` .next(Element)或 ` .completedevent` 事件。您无法使此流失败。所有其他绕过此限制的操作符 Infallible都具有相同的保证(例如,您不能调用 `as` Infallible.error而不是 `as` Observable.error)。
Driver如果你使用过 RxCocoa,你可能会想——嘿,这、和 之间有什么区别 Signal?
首先, Infallible`observable` 存在于 RxSwift 中,而另外两个则存在于 RxCocoa 中。但更重要的是,` observable` Driver和`observable` Signal始终使用 `RxSwift` MainScheduler并共享资源(使用 ` share()RxCocoa`)。而 `Infallible` 则不然,它完全是一个基础的可观察对象,仅在编译时保证其绝对可靠。
新 decode(type:decoder:)运营商 Observable<Data>
RxSwift 6 添加了一个专门用于 发出 `eval` 的 `s` 的 decode操作符 ,类似于 `s`: ObservableDataCombine
service . rx
. fetchJSONUsers () // Observable<Data>
. decode ( type : [ User ] . self , decoder : JSONDecoder ()) // Observable<[User]>
Enter fullscreen mode
Exit fullscreen mode
可变 drive()和 emit()
RxSwift 5 引入了可变参数(variadic) bind,它允许你执行以下操作:
viewModel . string . bind ( to : input1 , input2 , input3 )
Enter fullscreen mode
Exit fullscreen mode
DriverRxSwift 6 现在为s 和s 带来了相同的可变参数绑定 Signal——使用可变参数 driveand emit运算符:
viewModel . string . drive ( input1 , input2 , input3 )
viewModel . number . emit ( input4 , input5 )
Enter fullscreen mode
Exit fullscreen mode
Single现在更能效仿斯威夫特的做法 Result
在 RxSwift 5 之前, Single有一个自定义事件:
public enum SingleEvent < Element > {
case success ( Element )
case error ( Swift . Error )
}
Enter fullscreen mode
Exit fullscreen mode
如果你看着这个说,嘿——这看起来很像一个 Result<Element, Swift.Error>,那么你完全正确!
从 RxSwift 6 开始, SingleEvent它只是 的一个别名 Result<Element, Swift.Error>。
这一变化也体现在其他 API 中,例如 subscribe:
// RxSwift 5
single . subscribe (
onSuccess : { value in
print ( "Got a value: \( value ) " )
},
onError : { error in
print ( "Something went wrong: \( error ) " )
}
)
// RxSwift 6
single . subscribe (
onSuccess : { value in
print ( "Got a value: \( value ) " )
},
onFailure : { error in
print ( "Something went wrong: \( error ) " )
}
)
Enter fullscreen mode
Exit fullscreen mode
distinctUntilChange(at:)关键路径的 新运算符
distinctUntilChanged是一个非常有用的运算符,它允许你丢弃相同值的排放,以避免浪费地处理它们。
例如:
myStream . distinctUntilChanged { $0 . searchTerm == $1 . searchTerm }
Enter fullscreen mode
Exit fullscreen mode
键路径在这里又派上了用场。从 RxSwift 6 开始,你可以直接这样写:
myStream . distinctUntilChanged ( at : \ . searchTerm )
Enter fullscreen mode
Exit fullscreen mode
新的 ReplayRelay
中继会围绕主题进行封装,并允许你以只处理值的方式中继消息,因为中继保证永远不会失败或完成。
ReplayRelay是 RxSwift 6 的最新新增功能,它封装了 ReplaySubject,此外还包括现有的 BehaviorRelay和 PublishRelay。
创建它使用的界面与创建 ReplaySubject:
// Subject
ReplaySubject < Int >. create ( bufferSize : 3 )
// Relay
ReplayRelay < Int >. create ( bufferSize : 3 )
Enter fullscreen mode
Exit fullscreen mode
新 DisposeBag函数构建器
RxSwift 6 包含一个新的 DisposeBag函数构建器,支持类似 SwiftUI 的无逗号语法:
var disposeBag = DisposeBag {
observable1 . bind ( to : input1 )
observable2 . drive ( input2 )
observable3 . subscribe ( onNext : { val in
print ( "Got \( val ) " )
})
}
// Also works for insertions
disposeBag . insert {
observable4 . subscribe ()
observable5 . bind ( to : input5 )
}
Enter fullscreen mode
Exit fullscreen mode
许多(许多)运算符重命名
我们在 RxSwift 6 中花时间重命名了许多运算符,以便尽可能更好地遵守 Swift 的代码规范。
以下是一份基本完整的清单:
RxSwift 5
RxSwift 6
catchError(_:)
catch(_:)
catchErrorJustReturn(_:)
catchAndReturn(_:)
elementAt(_:)
element(at:)
retryWhen(_:)
retry(when:)
takeUntil(_:)
take(until:)
takeUntil(behavior:_:)
take(until:behavior:)
takeWhile(_:)
take(while:)
takeWhile(behavior:_:)
take(while:behavior:)
take(.seconds(3))
take(for: .seconds(3))
skipWhile(_:)
skip(while:)
takeUntil(_:)
take(until:)
observeOn(_:)
observe(on:)
subscribeOn(_:)
subscribe(on:)
更好地支持 XCFrameworks
现在,每个 RxSwift 6 版本都会捆绑一组 XCFrameworks。
由于二进制模块的稳定性,升级到下一个 Swift 版本时,无需担心向前兼容性,即可轻松链接到预构建的 RxSwift 副本。
结束!
希望您喜欢这篇关于 RxSwift 6 一些最有趣的功能和更新的快速概述,但这并不是全部修复的问题。
本次更新包含 大量 错误修复、性能改进和新增功能,非常值得一试。请务必花点时间阅读 更新说明 。
Rx 是 通过接口表达的 计算的通用抽象 Observable<Element>,它允许您广播和订阅来自 Observable流的值和其他事件。
RxSwift 是响应式扩展 标准针对 Swift 的实现 。
虽然此版本旨在忠实于 Rx 的原始精神和命名约定,但该项目也旨在为 Rx API 提供真正的 Swift 优先 API。
跨平台文档可在ReactiveX.io 上找到 。
与其他 Rx 实现一样,RxSwift 的目的是以对象的形式轻松组合异步操作和数据流 Observable,并提供一套方法来转换和组合这些异步工作片段。
KVO 观察、异步操作、UI 事件和其他数据流都被统一在 序列抽象 之下。这就是 Rx 如此简洁、优雅且强大的原因。
我来这里是因为我想 …
我们下篇博文再见,希望您喜欢 RxSwift 6!
文章来源:https://dev.to/freak4pc/what-s-new-in-rxswift-6-2nog