就我自己感覺而言,使用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
- 準備一些需要用但是沒有的方法
// 這四個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)
}
- 創(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
}
- 擴展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)一性诫舅,又可以當做中間層,隔離第三方宫患。