首页 > 滚动 > > 内容页

你应该知道的5个Swift组合变换操作符

2023-05-05 12:12:59 来源:清一色财经 分享到 :

想随时随地轻松变更数据格式?本文将教你5种解法!我将在Xcode Playground中创建示例函数,运行它们并观察结果。

本文转载自公众号“读芯术”(ID:AI_Discovery)。


(资料图片)

想随时随地轻松变更数据格式?本文将教你5种解法!我将在Xcode Playground中创建示例函数,运行它们并观察结果。

[[334295]]

1. map

.map 操作符允许我们转换闭包中来自发布者的所有元素。

varsubscriptions=Set()funcmapExample(){letsubject=PassthroughSubject()subject.map{(integer)inreturnString(integer)}.sink(receiveValue:{print("Value:\($0),Type:\(type(of:$0))")}).store(in:&subscriptions)subject.send(12)subject.send(31)subject.send(55)subject.send(4)subject.send(18)}

下面是这段代码的作用:

创建一个接受Int 值的PassthroughSubject。使用.map 操作符将每个接收到的Int 值转换为String。然后,订阅发布者并打印转换后的元素的值和类型。

向受试者发送随机数以观察以下结果:

还有一种巧妙的方法来使用对象的键路径获取对象的属性:

funcmapKeyPathExample(){structCarBrand{lettitle:Stringletcountry:String}letcarBrandsSubject=PassthroughSubject()carBrandsSubject.map(\.country).sink(receiveValue:{countryinprint("Country:\(country)")}).store(in:&subscriptions)carBrandsSubject.send(CarBrand(title:"MercedesBenz",country:"Germany"))carBrandsSubject.send(CarBrand(title:"Ford",country:"USA"))carBrandsSubject.send(CarBrand(title:"Honda",country:"Japan"))}

使用.map(\.country),可以访问CarBrand的国家属性。然后只需打印每个国家:

2. replaceNil

顾名思义,.replaceNil 操作符将每个接收到的nil元素转换为指定的元素:

funcreplaceNilExample(){letvalues:[Int?]=[123,nil,nil,12,10]letvaluesvaluesPublisher=values.publishervaluesPublisher.replaceNil(with:0).map{$0!}.collect().sink(receiveValue:{print($0)}).store(in:&subscriptions)}

请注意,还可以将多个操作符组合在一起以达到必要的结果。首先将每个nil 值替换为0,然后强制解开值,最后将所有值收集在一个数组中:

需要注意的是在.map 操作符中使用强制展开的方法。如果你不喜欢强行解包该怎么办?我们还有一个.map协变量:.compactMap,它能自动转发仅非零的那些元素:

funcreplaceNilExample(){letvalues:[Int?]=[123,nil,nil,12,10]letvaluesvaluesPublisher=values.publishervaluesPublisher.replaceNil(with:0).compactMap{$0}.collect().sink(receiveValue:{print($0)}).store(in:&subscriptions)}

3. collect

使用.collect操作符可以很容易地收集所有接收到的元素,并发出一个包含所有元素的数组:

funccollectExample(){letintegers=[1,4,5,12,24,44]letintegerPublisher=integers.publisherintegerPublisher.collect().sink(receiveValue:{print($0)}).store(in:&subscriptions)}

于是我们得到了想要的结果:

注意,发布者必须发出.completed事件才能实现这个操作,因为.collect会一直等待,直到所有元素都发出并且发布者完成操作为止。例如,如果使用PassthroughSubject,需要在发送所有元素后发送.finished事件:

funccollectExample(){letintegerPublisher=PassthroughSubject()integerPublisher.collect().sink(receiveValue:{print($0)}).store(in:&subscriptions)integerPublisher.send(1)integerPublisher.send(4)integerPublisher.send(5)integerPublisher.send(12)integerPublisher.send(24)integerPublisher.send(44)integerPublisher.send(completion:.finished)}

4. flatMap

.flatMap操作符允许我们将给定的发布者转换为另一个发布者。来看看它是如何将观察结果从Network更改为isAvailable主题:

funccollectExample(){letintegerPublisher=PassthroughSubject()integerPublisher.collect().sink(receiveValue:{print($0)}).store(in:&subscriptions)integerPublisher.send(1)integerPublisher.send(4)integerPublisher.send(5)integerPublisher.send(12)integerPublisher.send(24)integerPublisher.send(44)integerPublisher.send(completion:.finished)}

当更改它的值时,我们要打印出isAvailable值。首先,它打印初始值(正在使用CurrentValueSubject),一旦为其分配了新值,就会发生以下情况:

5. scan

.scan操作符能够在闭包中公开当前发出的值以及最新的值。可以使用它来累积值并打印总结果:

funcflatMapExample(){structNetwork{lettitle:StringletisAvailable=CurrentValueSubject(false)}letwifi=Network(title:"Wi-Fi")letnetworkSubject=CurrentValueSubject(wifi)networkSubject.flatMap({return$0.isAvailable}).sink(receiveValue:{print("Isnetworkenabled:\($0)")}).store(in:&subscriptions)wifi.isAvailable.value=truewifi.isAvailable.value=false}

在这里,执行的是以下操作:

创建收益数组(下划线是将数字中的千单位分开的好方法)。创建这些收益的发布者。使用.scan操作符,将当前发出的值($0)添加到从零开始的最新值($1)。

最后,计算出总收益:

【责任编辑:赵宁宁 TEL:(010)68476606】

推荐阅读