代理支持rxSwift

就我自己感覺而言,使用Swift在書寫上更加簡潔畦幢、便于擴展坎吻、和oc橋接也很簡單。而且Swift已經是第三個大版本了宇葱,今年的開發(fā)者大會也基本沒有提swift的事瘦真,說明Swift已經相當穩(wěn)定了。Swift的發(fā)展趨勢也不錯黍瞧,普及應該是早晚的事诸尽。
在Swift社區(qū),rxSwift是一個相當有影響力印颤,且值得一用的Api您机。各個社區(qū)關于rxSwift的教程也有很多,它本身的文檔也非常詳細年局。
本文主要分享一下我自己的使用過程中感覺非常有趣的一個小tip: 自定義的代理手動支持rxSwift际看。

集成:
pod 直接集成就可以。(?我覺得考慮這么做的前提是項目中正在使用rxSwift矢否。不然仿村,真沒必要)

    pod 'RxSwift'
    pod 'RxCocoa'

一、 準備好要搞的代理兴喂,只是一個demo蔼囊,所以代碼是毫無營養(yǎng)的

@objc protocol DemoDelegate: NSObjectProtocol {
    @objc optional func demo(d: Demo, didSetName name: String)
}

class Demo: NSObject {
    weak public var delegate: DemoDelegate?
    
    public var name: String? {
        didSet {
            if let n = name {
                self.delegate?.demo?(d: self, didSetName: n)
            }
        }
    }
}

二焚志、 準備工作
創(chuàng)建一個單獨的文件,如果是第三方的代理就引入代理所在的頭文件畏鼓,如果是項目里的就不用了酱酬。下面兩個頭文件還是要引入的。

import RxCocoa
import RxSwift
  1. 準備一些需要用但是沒有的方法
// 這四個func 是rxSwift的錯誤處理方法云矫,沒有用public修飾膳沽,無法直接使用,拷貝當前文件就可以用啦让禀。
func castOrThrow<T>(_ resultType: T.Type, _ object: Any) throws -> T {
    guard let returnValue = object as? T else {
        throw RxCocoaError.castingError(object: object, targetType: resultType)
    }
    
    return returnValue
}

func castOptionalOrFatalError<T>(_ value: Any?) -> T? {
    if value == nil {
        return nil
    }
    let v: T = castOrFatalError(value)
    return v
}

func castOrFatalError<T>(_ value: Any!) -> T {
    let maybeResult: T? = value as? T
    guard let result = maybeResult else {
        rxFatalError("Failure converting from &&\(value)&& to \(T.self)")
    }
    return result
}

func rxFatalError(_ lastMessage: String) -> Never  {
    fatalError(lastMessage)
}
  1. 創(chuàng)建RxDelegateDemoDelegateProxy類繼承自RxCocoa.DelegateProxy挑社,并遵守DelegateProxyType協(xié)議以及目標代理DemoDelegate
    <1> override父類方法
override public class func createProxyForObject(_ object: AnyObject) -> AnyObject {
        let p: Demo = castOrFatalError(object)
        return p.createRxDelegateProxy()
    }

<2> 實現DelegateProxyType中代理的set和get方法

public class func setCurrentDelegate(_ delegate: AnyObject?, toObject object: AnyObject) {
        let p: Demo = castOrFatalError(object)
        p.delegate = castOptionalOrFatalError(delegate)
    }
public class func currentDelegateFor(_ object: AnyObject) -> AnyObject? {
        let p: Demo = castOrFatalError(object)
        return p.delegate
    }
  1. 擴展Demo類
extension Demo {
    public func createRxDelegateProxy() -> RxDelegateDemoDelegateProxy {
        return RxDelegateDemoDelegateProxy(parentObject: self)
    }
}

三、 準備就緒巡揍,擴展rxSwift的Reactive痛阻,這是一個結構體。

extension Reactive where Base: Demo {
    //  實現這個腮敌,創(chuàng)建的類(本文是Demo)類的對象就可以點出rx了
    var delegate: DelegateProxy {
        return RxDelegateDemoDelegateProxy.proxyForObject(base)
    }
   //  ControlEvent<>的尖括號里可以是單個類型,也可以是組元糜工。組元用于監(jiān)聽多個參數弊添。
    var didSetName: ControlEvent<String> {
       /**
          DelegateProxy的對象方法 methodInvoked 。
          點到這個方法里捌木,有一大坨的注釋解釋這個方法油坝。
          大概的意思是說methodInvoked方法只能監(jiān)聽返回值是Void的代理方法。
          有返回值的代理方法要用PublishSubject這個監(jiān)聽刨裆,還給了個例子澈圈,有興趣可以點進去看一下。
        */
        let source = delegate.methodInvoked(#selector(DemoDelegate.demo(d:didSetName:))).map({ (a:[Any]) -> String in
            // map函數可以接收到代理方法的參數崔拥〖颍可以是單個參數凤覆,也可以是多個參數链瓦。根據需要取值就可以了,根據參數在代理方法中的位置盯桦,下標從0開始慈俯。本文實現中,只需要第二個參數拥峦,數以取1.
            let i = try castOrThrow(String.self, a[1])
            return i
        })
        //  創(chuàng)建event返回
        return ControlEvent(events: source)
    }
}

到此為止贴膘,自定義的代理也可以使用rxSwift監(jiān)聽了。當然在實際Swift中這樣的感覺多寫了不少略号。而且很多數據刑峡、事件的傳遞用閉包就輕松搞定了洋闽。
但是,也可以用同樣的方法讓第三方中的代理支持rxSwift這樣的鏈式調用突梦,既可以保持代碼的統(tǒng)一性诫舅,又可以當做中間層,隔離第三方宫患。

源碼:RxSwiftTipDemo

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末刊懈,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子娃闲,更是在濱河造成了極大的恐慌虚汛,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件皇帮,死亡現場離奇詭異卷哩,居然都是意外死亡,警方通過查閱死者的電腦和手機玲献,發(fā)現死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門殉疼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人捌年,你說我怎么就攤上這事瓢娜。” “怎么了礼预?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵眠砾,是天一觀的道長。 經常有香客問我托酸,道長褒颈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任励堡,我火速辦了婚禮谷丸,結果婚禮上,老公的妹妹穿的比我還像新娘应结。我一直安慰自己刨疼,他們只是感情好,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布鹅龄。 她就那樣靜靜地躺著揩慕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪扮休。 梳的紋絲不亂的頭發(fā)上迎卤,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機與錄音玷坠,去河邊找鬼蜗搔。 笑死劲藐,一個胖子當著我的面吹牛,可吹牛的內容都是我干的樟凄。 我是一名探鬼主播瘩燥,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼不同!你這毒婦竟也來了厉膀?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤二拐,失蹤者是張志新(化名)和其女友劉穎服鹅,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體百新,經...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡企软,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了饭望。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仗哨。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖铅辞,靈堂內的尸體忽然破棺而出厌漂,到底是詐尸還是另有隱情,我是刑警寧澤斟珊,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布苇倡,位于F島的核電站,受9級特大地震影響囤踩,放射性物質發(fā)生泄漏旨椒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一堵漱、第九天 我趴在偏房一處隱蔽的房頂上張望综慎。 院中可真熱鬧,春花似錦勤庐、人聲如沸示惊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽涝涤。三九已至媚狰,卻和暖如春岛杀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背崭孤。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工类嗤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留糊肠,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓遗锣,卻偏偏與公主長得像货裹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子精偿,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內容

  • 發(fā)現 關注 消息 iOS 第三方庫弧圆、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,103評論 4 62
  • 在我們的生活中笔咽,很多的地方都出現過吉他這種樂器搔预,可是雖然這種樂器很酷,可是在背后的努力叶组,那真是很苦啊 ...
    期待待續(xù)閱讀 183評論 0 1
  • 嚴如斯每一天和來酒吧消遣的各色人等打交道拯田,對各種突發(fā)事件都處理的游刃有余。這本領的練就需要的不止是忍氣吞聲甩十,低眉順...
    樵砥閱讀 241評論 2 1
  • 到了一個陌生的村莊船庇,一個剛畢業(yè)的大學生該干些什么? 沒錯侣监,熟悉村中的情況鸭轮。一家家走訪,逮著誰就問橄霉。村里人遇到一個陌...
    毛線兄閱讀 99評論 0 0