Swift Combine 之 Publisher的sink和assign

Subscriber(這篇文章主要講assignsink

  • Publisher中末尾提到了sinkassign的調(diào)用嫂沉,現(xiàn)在具體看一下具體做了什么

sink操作符的代碼調(diào)用

```
    let arr: [Int] = [1, 2, 100]
     
     /// `Sink` 將數(shù)組轉(zhuǎn)換成一個(gè)數(shù)據(jù)流
    arr.publisher
         /// 過濾數(shù)據(jù)流中大于2的元素
         .filter{$0 > 2}
         /// 進(jìn)行一次轉(zhuǎn)換稽寒,轉(zhuǎn)成String類型
         .compactMap{"\($0)"}
         /// 訂閱數(shù)據(jù)源
         .sink { value in
             debugPrint("數(shù)據(jù)流: \(value)")
         }.store(in: &cancel)
 ```

Sink

  • 之前講解了Publisher的數(shù)據(jù)流發(fā)布的過程,sink相當(dāng)于接收publisher發(fā)送的數(shù)據(jù)趟章,然后執(zhí)行receiveValue閉包杏糙,調(diào)用者可以進(jìn)行自己的業(yè)務(wù)處理

  • 先看一下sink操作符

    public func sink(
         receiveValue: @escaping (Output) -> Void
     ) -> AnyCancellable {
        /// 包裝類`Sink`處理數(shù)據(jù)流,然后回調(diào)給receiveValue閉包
         let subscriber = Subscribers.Sink<Output, Failure>(
             receiveCompletion: { _ in },
             receiveValue: receiveValue
         )
         /// 訂閱數(shù)據(jù)流
         subscribe(subscriber)
         /// GC 包裝類
         return AnyCancellable(subscriber)
     }
    
  • Sink包裝類實(shí)現(xiàn)

  • /// A simple subscriber that requests an unlimited number of values upon subscription.
       public final class Sink<Input, Failure: Error>
           : Subscriber,
             Cancellable
       {
           /// 持有外部的閉包
           public var receiveValue: (Input) -> Void
    
           /// 完成閉包
           public var receiveCompletion: (Subscribers.Completion<Failure>) -> Void
    
           /// 狀態(tài)
           private var status = SubscriptionStatus.awaitingSubscription
    
           /// 初始化持有完成回調(diào)閉包和數(shù)據(jù)流回調(diào)閉包
           public init(
               receiveCompletion: @escaping (Subscribers.Completion<Failure>) -> Void,
               receiveValue: @escaping ((Input) -> Void)
           ) {
               self.receiveCompletion = receiveCompletion
               self.receiveValue = receiveValue
           }
    
           /// `Subscription`協(xié)議方法實(shí)現(xiàn)
           public func receive(subscription: Subscription) {
    
               guard case .awaitingSubscription = status else {
          
                   subscription.cancel()
                   return
               }
               subscription.request(.unlimited)
           }
           /// `Subscribers` 協(xié)議實(shí)現(xiàn)蚓土,執(zhí)行數(shù)據(jù)流回調(diào)
           public func receive(_ value: Input) -> Subscribers.Demand {
               /// 記錄當(dāng)前的數(shù)據(jù)流回調(diào)
               let receiveValue = self.receiveValue
               /// 觸發(fā)數(shù)據(jù)流回調(diào)
               receiveValue(value)
               return .none
           }
           
           /// `Subscribers` 完成回調(diào)
           public func receive(completion: Subscribers.Completion<Failure>) {
    
               let receiveCompletion = self.receiveCompletion
               self.receiveCompletion = { _ in }
    
               withExtendedLifetime(receiveValue) {
                   receiveValue = { _ in }
               }
               /// 執(zhí)行完成回調(diào)
               receiveCompletion(completion)
           }
    
           /// 數(shù)據(jù)流取消(`cancel`)
           public func cancel() {
    
               guard case let .subscribed(subscription) = status else {
                   return
               }
    
               withExtendedLifetime((receiveValue, receiveCompletion)) {
                   receiveCompletion = { _ in }
                   receiveValue = { _ in }
               }
               subscription.cancel()
           }
       }
    

assign操作符代碼調(diào)用

```
let arr: [Int] = [1, 2, 100]
     
      /// `Assign`使用keypath進(jìn)行賦值
     arr.publisher
         .filter{$0 > 2}
         .compactMap{"\($0)"}
         /// keypath 賦值
         .assign(to: \.name, on: root).store(in: &cancel)
     
     debugPrint("root name: \(root.name)")
```

Assign

  • 使用KeyPath來實(shí)現(xiàn)具體類的賦值操作宏侍,僅支持Class類型的具體類

  • assign操作符

      public func assign<Root>(to keyPath: ReferenceWritableKeyPath<Root, Output>,
                               on object: Root) -> AnyCancellable {
          /// 訂閱類,`Assign`進(jìn)行了包裝蜀漆,數(shù)據(jù)流流轉(zhuǎn)到這里進(jìn)行keypath賦值    
          let subscriber = Subscribers.Assign(object: object, keyPath: keyPath)
          /// 訂閱數(shù)據(jù)流
          subscribe(subscriber)
         /// GC 處理
          return AnyCancellable(subscriber)
      }
    
  • Assign包裝類

  • public final class Assign<Root, Input>: Subscriber,
                                               Cancellable
       {
           public typealias Failure = Never
    
           public private(set) var object: Root?
    
           /// The key path that indicates the property to assign.
           public let keyPath: ReferenceWritableKeyPath<Root, Input>
    
           private var status = SubscriptionStatus.awaitingSubscription
    
    
           /// 持有keypath的關(guān)聯(lián)類和keypath的鍵
           public init(object: Root, keyPath: ReferenceWritableKeyPath<Root, Input>) {
               self.object = object
               self.keyPath = keyPath
           }
    
           public func receive(subscription: Subscription) {
    
               guard case .awaitingSubscription = status else {
                   subscription.cancel()
                   return
               }
               status = .subscribed(subscription)
               subscription.request(.unlimited)
           }
    
           /// 數(shù)據(jù)流流轉(zhuǎn)到這里谅河,進(jìn)行keypath賦值
           public func receive(_ value: Input) -> Subscribers.Demand {
    
               guard case .subscribed = status, let object = self.object else {
                   return .none
               }
               object[keyPath: keyPath] = value
               return .none
           }
    
           /// 完成回調(diào)
           public func receive(completion: Subscribers.Completion<Never>) {
               guard case .subscribed = status else {
                   return
               }
               terminateAndConsumeLock()
           }
    
           public func cancel() {
               guard case let .subscribed(subscription) = status else {
                   return
               }
               terminateAndConsumeLock()
               subscription.cancel()
           }
    
           private func terminateAndConsumeLock() {
               withExtendedLifetime(object) {
                   object = nil
               }
           }
       }
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市确丢,隨后出現(xiàn)的幾起案子绷耍,更是在濱河造成了極大的恐慌,老刑警劉巖鲜侥,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件褂始,死亡現(xiàn)場離奇詭異,居然都是意外死亡描函,警方通過查閱死者的電腦和手機(jī)崎苗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來舀寓,“玉大人益缠,你說我怎么就攤上這事』” “怎么了幅慌?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長轰豆。 經(jīng)常有香客問我胰伍,道長,這世上最難降的妖魔是什么酸休? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任骂租,我火速辦了婚禮,結(jié)果婚禮上斑司,老公的妹妹穿的比我還像新娘渗饮。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布互站。 她就那樣靜靜地躺著私蕾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪胡桃。 梳的紋絲不亂的頭發(fā)上踩叭,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天,我揣著相機(jī)與錄音翠胰,去河邊找鬼容贝。 笑死,一個(gè)胖子當(dāng)著我的面吹牛之景,可吹牛的內(nèi)容都是我干的斤富。 我是一名探鬼主播,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼锻狗,長吁一口氣:“原來是場噩夢啊……” “哼满力!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起屋谭,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤脚囊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后桐磁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體悔耘,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年我擂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了衬以。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,764評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡校摩,死狀恐怖看峻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情衙吩,我是刑警寧澤互妓,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站坤塞,受9級特大地震影響冯勉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜摹芙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一灼狰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧浮禾,春花似錦交胚、人聲如沸份汗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽杯活。三九已至,卻和暖如春军熏,著一層夾襖步出監(jiān)牢的瞬間轩猩,已是汗流浹背卷扮。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工荡澎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人晤锹。 一個(gè)月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓摩幔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鞭铆。 傳聞我的和親對象是個(gè)殘疾皇子或衡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Combine之核心概念 Combine解決的核心問題是如何處理時(shí)間序列數(shù)據(jù),也就是隨著時(shí)間變化而變化的數(shù)據(jù)车遂。它有...
    同分異構(gòu)腦閱讀 351評論 0 0
  • Publisher 根據(jù) Subscriber 的請求提供數(shù)據(jù)封断。如果沒有任何訂閱請求,Publisher 不會提供...
    YungFan閱讀 616評論 0 1
  • Java 是響應(yīng)式編程(Reactive Programming)在 Java 語言上的實(shí)現(xiàn) 主要內(nèi)容: RxJa...
    非程序員閱讀 586評論 0 0
  • 在復(fù)雜的分布式應(yīng)用中有著許多的依賴舶担,各個(gè)依賴都有難免在某個(gè)時(shí)刻失敗坡疼,如果應(yīng)用不隔離各個(gè)依賴,降低外部的風(fēng)險(xiǎn)衣陶,那容易...
    陳二狗想吃肉閱讀 689評論 0 3
  • IOS App 審核指南 原文地址: https://developer.apple.com/app-store/...
    袁俊亮技術(shù)博客閱讀 3,107評論 1 1