iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 9
1
自我挑戰組

30 天了解 Swift 的 Combine系列 第 9

30 天了解 Swift 的 Combine: [09] Operator 目錄 + 第一部分:轉換類型

  • 分享至 

  • xImage
  •  

基本觀念的最後一個部分,Operator,就像是物件導向的不同部分有不同的變形一樣,Operator 在 Combine 中扮演了舉足輕重的角色,沒有了他,Combine 只是 if then

Operator 可以區分為一下大類

轉換類型 map, scan, flapMap
一般篩選類型 compactMap, filter, removeDuplicates
整併類型 reduce, collect
運算類型 count, comparison
符合篩選類型 contains, allSatisfy
序列篩選類型 first, last, drop, firstWhere,
上流整合類型 zip, merge, combineLatest
型別銜接類型 eraseToAnyPublisher, switchToLatest
失敗處理類型 catch, retry, mapError
時間控制類型 debounce, throttle, delay, timeout
格式解析類型 Encode, decode
Debugging類型 print, breakpoint, handleEvents

因版面關係,略過錯誤情形,例如tryMap, 詳細請參考 Publishers namespace

接下來會依序介紹 Operator,配合 Marbles diagram,介紹Operator。

Operator 1. 轉換類型

1. map: 轉換上游元素為另一元素

讓我想到 Array.map,若以這個角度來看是像的。

func map<T>(_ transform: @escaping (Self.Output) -> T) -> Publishers.Map<Self, T>

transform: 元素映射閉包, 帶入上游元素,回傳新元素。

Return Value
Publisher 使用上游提供的元素映射閉包, 並套用於隨後發布的新元素。

******demo code*******
Just("1")
            .map(atof)
            .dprint()
            .sink{_ in}

******console*********
FILETests.swift 1: receive subscription: (Just)
FILETests.swift 1: request unlimited
FILETests.swift 1: receive value: (1)
FILETests.swift 1: receive finished

*******Rarbles********

------("1")------|

    map(atof)
    
------(1.0)------|

2. scan 類似 map,但是可以取得前一個上路元素。

讓我想到 Array.reduce,若以這個角度來看很清楚。

func scan<T>(_ initialResult: T, _ nextPartialResult: @escaping (T, Self.Output) -> T) -> Publishers.Scan<Self, T>

Parameters
initialResult
初試值,同時確定 return Publisher.Output


nextPartialResult
元素映射閉包,附帶兩個帶出參數,分別是
A closure that takes as its arguments the previous value returned by the closure and the next element emitted from the upstream publisher.

*****demo code*******

[1,0,3].publisher
            .dprint() // ? before
            .scan(0){max($0,$1)}
            .dprint() // ? after
            .sink{_ in}

*****console*********

FILETests.swift ?: receive subscription: ([1, 0, 3])
FILETests.swift ?: receive subscription: (Print)
FILETests.swift ?: request unlimited
FILETests.swift ?: request unlimited
FILETests.swift ?: receive value: (1)
FILETests.swift ?: receive value: (0)
FILETests.swift ?: receive value: (0)
FILETests.swift ?: receive value: (0)
FILETests.swift ?: receive value: (3)
FILETests.swift ?: receive value: (0)
FILETests.swift ?: receive finished
FILETests.swift ?: receive finished

*******Rarbles*******
-1--------0---------3-|

scan(0){max($0,$1)}

-1--------1---------3-|

3. flatMap 轉換上流至現有或新的 Publisher

(試解釋)將上流的事件以延伸流的方式執行邏輯處理,吧
p.s. 據說這是最難懂的!老實說筆者在寫的時候還沒搞懂,

func flatMap<T, P>(maxPublishers: Subscribers.Demand = .unlimited, _ transform: @escaping (Self.Output) -> P) -> Publishers.FlatMap<P, Self> where T == P.Output, P : Publisher, Self.Failure == P.Failure

Parameters
maxPublishers
//The maximum number of publishers produced by this method.

transform
//A closure that takes an element as a parameter and returns a publisher that produces elements of that type.

Return Value
//A publisher that transforms elements from an upstream publisher into a publisher of that element’s type.

Discussion
flatMap merges the output from all returned publishers into a single stream of output.


******demo code*******
        _ = [
                "1.2".data(using: .utf8)!, 
                "1".data(using: .utf8)!
            ].publisher
            .flatMap{
                return Just($0)
                    .decode(type: Int.self, decoder: JSONDecoder())
                    .catch{_ in return Just(0)}
        }
        .dprint()
        .sink{_ in}

******console*********

FILETests.swift 1: receive subscription: (FlatMap)
FILETests.swift 1: request unlimited
FILETests.swift 1: receive value: (0)
FILETests.swift 1: receive value: (1)
FILETests.swift 1: receive finished

*******Rarbles********

---"1.2"----------"1"|

 flatMap          
    +Decode        +Decode
    ----X            ----1
    +catch
        0|
      
      
------0------------------1|      

有趣的是,我嘗試使用 .map{}.switchtoLast() 也可以得到結果!所以 flatMap 是這個的化簡嗎? ?

簡單測驗:

  1. 嘗試閱讀 ReactiveX 的 Decision tree
  2. 嘗試解釋Publishers.FlatMapArray.flatMap (other language's compactMap) 差別

whoami:
我是游諭 ytyubox


上一篇
30 天了解 Swift 的 Combine: [08] Publisher 延展類:Subject
下一篇
30 天了解 Swift 的 Combine: [10] Operator 2: 一般篩選類型
系列文
30 天了解 Swift 的 Combine30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言