RxSwift 原理及使用经验

2017/03/10

原理

RxCocoa如何将Cocoa对象的消息转化为可被订阅的流

        let button = UIButton()
        button.rx.sentMessage(#selector(UIButton.setTitle(_:for:)))
            .asObservable().subscribe { (event) in
                print( "event : \(event)") //next([Title, 0])
            }
            .addDisposableTo(disposeBag)
        button.setTitle("Title", for: UIControlState.normal)

像这样的一段代码,表示RxCocoa将Cocoa的对象消息全都拦截并转化成了可以被订阅的Observable

首先分析 UIButton 的rx的属性是怎么来的呢?

/// Extend NSObject with `rx` proxy.
extension NSObject: ReactiveCompatible { }

public protocol ReactiveCompatible {
    associatedtype CompatibleType
    static var rx: Reactive<CompatibleType>.Type { get set }
    var rx: Reactive<CompatibleType> { get set }
}

extension ReactiveCompatible {
    public static var rx: Reactive<Self>.Type {
        get {
            return Reactive<Self>.self
        }
        set {
            // this enables using Reactive to "mutate" base type
        }
    }

    public var rx: Reactive<Self> {
        get {
            return Reactive(self)
        }
        set {
            // this enables using Reactive to "mutate" base object
        }
    }
}

public struct Reactive<Base> {
    public let base: Base
    public init(_ base: Base) {
        self.base = base
    }
}

给 NSObject 添加了一个 ReactiveCompatible 协议 ,并对这个协议作扩展了。也就是给所有NSObject都添加了 .rx 的属性,这个属性返回的是一个叫Reactive的容器,容器里就是原本的对象。 这个容器有意思了,不仅能把RxCocoa的api全都用 .rx. 这样的方式和Cocoa的api都区分开,还能为这个容器实现更多的协议,扩展出更多的方法。用where约束的办法,扩展出针对某个Cocoa对象独特的rx方法。

extension Reactive where Base: UIButton {

    /// Reactive wrapper for `TouchUpInside` control event.
    public var tap: ControlEvent<Void> {
        return controlEvent(.touchUpInside)
    }
}

接下来看看 sentMassage方法:

extension Reactive where Base: AnyObject {
    public func sentMessage(_ selector: Selector) -> Observable<[Any]> {
        return synchronized {
            // in case of dealloc selector replay subject behavior needs to be used
            if selector == deallocSelector {
                return deallocating.map { _ in [] }
            }

            do {
                let proxy: MessageSentProxy = try registerMessageInterceptor(selector)
                return proxy.messageSent.asObservable()
            }
            catch let e {
                return Observable.error(e)
            }
        }
    }
}

这里先主要看它返回的是一个 MessageSentProxy 的类型 ,他有PublishSubject的功能,也就是可以对作为Observable,发送 .next(arguments) 等event事件。意味着被转化的事件流将由它向外发送。

然后继续看关键的函数 registerMessageInterceptor(selector) 为一个selector注册监听者。

    fileprivate func registerMessageInterceptor<T: MessageInterceptorSubject>(_ selector: Selector) throws -> T {
        let rxSelector = RX_selector(selector)
        let selectorReference = RX_reference_from_selector(rxSelector)

        let subject: T
        if let existingSubject = objc_getAssociatedObject(base, selectorReference) as? T {
            subject = existingSubject
        }
        else {
            subject = T()
            objc_setAssociatedObject(
                base,
                selectorReference,
                subject,
                .OBJC_ASSOCIATION_RETAIN_NONATOMIC
            )
        }

        if subject.isActive {
            return subject
        }

        var error: NSError?
        let targetImplementation = RX_ensure_observing(base, selector, &error)
        if targetImplementation == nil {
            throw error?.rxCocoaErrorForTarget(base) ?? RxCocoaError.unknown
        }

        subject.targetImplementation = targetImplementation!

        return subject
    }
#endif
}

生成了一个 MessageInterceptorSubject 对象并将它用 objc_getAssociatedObject方法绑定到这个 button Cocoa的实例上,以 selectorReference 为Key。目的是为这个实例 保存一个向外发送event事件的 subject。 等RX_ensure_observing里面会用selectorReference重新取出这个 subject,然后将监听到的消息都发给他。

继续看关键方法 RX_ensure_observing

IMP __nullable RX_ensure_observing(id __nonnull target, SEL __nonnull selector, NSError ** __nonnull error) {
    __block IMP targetImplementation = nil;
    @synchronized(target) {
        @synchronized([target class]) {
            [[RXObjCRuntime instance] performLocked:^(RXObjCRuntime * __nonnull self) {
                targetImplementation = [self ensurePrepared:target
                                               forObserving:selector
                                                      error:error];
            }];
        }
    }

    return targetImplementation;
}

[RXObjCRuntime instance] 这个实例是RxCocoa 用来操作所有运行时的一个单例,可以在这个单例调用运行时api加上各种锁,保证线程安全。

继续看 ensurePrepared: forObserving: error: 要开始为这个target的selector真正的注入监听者了。

-(IMP __nullable)ensurePrepared:(id __nonnull)target forObserving:(SEL __nonnull)selector error:(NSError** __nonnull)error {
	/* 一些安全代码 */
    if (selector == deallocSelector) {
		/* 一些针对dealloc特殊的处理代码 */
    }
    else {
            Class __nullable swizzlingImplementorClass = [self prepareTargetClassForObserving:target error:error];

		/* 一些优化消息监听性能的代码 */
        // optimized interception method
        if (optimizedIntercept != nil) {
		/* 一些优化消息监听性能的代码 */
        }
        // default fallback to observing by forwarding messages
        else {
            if ([self forwardingSelector:selector forClass:swizzlingImplementorClass]) {
                return RX_default_target_implementation();
            }

            if (![self observeByForwardingMessages:swizzlingImplementorClass
                                          selector:selector
                                            target:target
                                             error:error]) {
                return nil;
            }

            if ([self forwardingSelector:selector forClass:swizzlingImplementorClass]) {
                return RX_default_target_implementation();
            }
        }
    }
    /* 一些处理错误代码 */
}

[self prepareTargetClassForObserving:target error:error] 方法为target 这个类准备一个中间类 swizzlingImplementorClass 。为了替换 target的 isa 指针以拦截消息

-(Class __nullable)prepareTargetClassForObserving:(id __nonnull)target error:(NSError **__nonnull)error {
	/* 省略一些代码 */
    Class __nullable dynamicFakeSubclass = [self ensureHasDynamicFakeSubclass:wannaBeClass error:error];
    
    Class previousClass = object_setClass(target, dynamicFakeSubclass);//替换 *target*的 isa 指针以拦截消息 

    objc_setAssociatedObject(target, &RxSwizzlingTargetClassKey, dynamicFakeSubclass, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    return dynamicFakeSubclass;
}


-(Class __nullable)ensureHasDynamicFakeSubclass:(Class __nonnull)class error:(NSError **)error {
    Class dynamicFakeSubclass = self.dynamicSubclassByRealClass[CLASS_VALUE(class)];
    if (dynamicFakeSubclass != nil) {
        return dynamicFakeSubclass;
    }

    NSString *dynamicFakeSubclassName = [RX_PREFIX stringByAppendingString:NSStringFromClass(class)];
    const char *dynamicFakeSubclassNameRaw = dynamicFakeSubclassName.UTF8String;
    dynamicFakeSubclass = objc_allocateClassPair(class, dynamicFakeSubclassNameRaw, 0); //!!!创建中间类
    ALWAYS(dynamicFakeSubclass != nil, @"Class not generated");

    if (![self swizzleClass:dynamicFakeSubclass toActAs:class error:error]) {
        return nil;
    }//!!!修改中间类的class方法,欺骗

    objc_registerClassPair(dynamicFakeSubclass);//!!!动态注册生产好的中间类

    [self.dynamicSubclassByRealClass setObject:dynamicFakeSubclass forKey:CLASS_VALUE(class)];
    ALWAYS(self.dynamicSubclassByRealClass[CLASS_VALUE(class)] != nil, @"Class not registered");

    return dynamicFakeSubclass;
}

目前为止中间类就成功接管了,UIButton的所有方法。这个原理类似KVO的实现。但是这里不是重写Cocoa方法 而是将要监听的 selectorIMP 改成 _objc_msgForward 让这个消息走消息转发流程。最后重写 forwardInvocation: 函数统一处理消息。

-(BOOL)observeByForwardingMessages:(Class __nonnull)swizzlingImplementorClass
                          selector:(SEL)selector
                            target:(id __nonnull)target
                             error:(NSError **__nonnull)error {
    if (![self ensureForwardingMethodsAreSwizzled:swizzlingImplementorClass error:error]) {
        return NO;
    }
    SEL rxSelector = RX_selector(selector);

    Method instanceMethod = class_getInstanceMethod(swizzlingImplementorClass, selector);

    IMP implementation = method_getImplementation(instanceMethod);

    if (!class_addMethod(swizzlingImplementorClass, rxSelector, implementation, methodEncoding)) {
        RX_THROW_ERROR([NSError errorWithDomain:RXObjCRuntimeErrorDomain
                                           code:RXObjCRuntimeErrorSavingOriginalForwardingMethodFailed
                                       userInfo:nil], NO);
    }

    if (!class_addMethod(swizzlingImplementorClass, selector, _objc_msgForward, methodEncoding)) {
        if (implementation != method_setImplementation(instanceMethod, _objc_msgForward)) {
            THREADING_HAZARD(swizzlingImplementorClass);
            RX_THROW_ERROR([NSError errorWithDomain:RXObjCRuntimeErrorDomain
                                               code:RXObjCRuntimeErrorReplacingMethodWithForwardingImplementation
                                           userInfo:nil], NO);
        }
    }
    [self registerForwardedSelector:selector forClass:swizzlingImplementorClass];

    return YES;
}

ensureForwardingMethodsAreSwizzled 方法里替换了中间类的 forwardInvocation 为 新的IMP

-(BOOL)ensureForwardingMethodsAreSwizzled:(Class __nonnull)class error:(NSError ** __nonnull)error {
    NSValue *classValue = CLASS_VALUE(class);
    if ([self.classesThatSupportObservingByForwarding containsObject:classValue]) {
        return YES;
    }

    if (![self swizzleForwardInvocation:class error:error]) { return NO; }
    if (![self swizzleMethodSignatureForSelector:class error:error]) { return NO; }
    if (![self swizzleRespondsToSelector:class error:error]) { return NO; }

    [self.classesThatSupportObservingByForwarding addObject:classValue];

    return YES;
}

swizzleForwardInvocation 使用宏定义实现的。

SWIZZLE_INFRASTRUCTURE_METHOD(
    void,
    swizzleForwardInvocation,
    ,
    @selector(forwardInvocation:),
    FORWARD_BODY,
    NSInvocationRef
)
// RX_forward_invocation 将捕获到的方法和参数 发送给 之前用 selector为key的subject。
#define FORWARD_BODY(invocation)
if (RX_forward_invocation(self, NAME_CAT(_, 0, invocation))) { return; }

//宏展开的主要部分
        id newImplementation = ^return_value(__unsafe_unretained id self DECLARE_ARGUMENTS(__VA_ARGS__)) {               \
            FORWARD_BODY(__VA_ARGS__)      //这里调用  RX_forward_invocation 函数。                                                                                   
            struct objc_super superInfo = {\
                .receiver = self,                                                                                        
                .super_class = class_getSuperclass(class)                                                                
            };                                                                                                           
            return_value (*msgSend)(struct objc_super *, SEL DECLARE_ARGUMENTS(__VA_ARGS__))  //                            \
                = (__typeof__(msgSend))objc_msgSendSuper;                                                                \

主要是 RX_forward_invocation 将捕获到的方法和参数 发送给 之前用 selector为key的subject。 将新的 newImplementation IMP 替换到原来的forwardInvocation:上。在 RX_forward_invocation 转发完消息后。也要把消息传给 父类 :UIButton。继续这个消息的任务。

static BOOL RX_forward_invocation(id __nonnull __unsafe_unretained self, NSInvocation *invocation) {
    SEL originalSelector = RX_selector(invocation.selector);

    id<RXMessageSentObserver> messageSentObserver = objc_getAssociatedObject(self, originalSelector);

    if (messageSentObserver != nil) {
        NSArray *arguments = RX_extract_arguments(invocation);
        [messageSentObserver messageSentWithArguments:arguments];
    }

    if ([self respondsToSelector:originalSelector]) {
        invocation.selector = originalSelector;
        [invocation invokeWithTarget:self];

        if (messageSentObserver != nil) {
            NSArray *arguments = RX_extract_arguments(invocation);
            [messageSentObserver methodInvokedWithArguments:arguments];
        }

        return YES;
    }

    return NO;
}

监听UIKit对象的Delegate的方法

        let web = UIWebView()
        web.loadRequest(URLRequest(url: URL(string:"baidu.com")!))
        web.rx.didStartLoad
            .asObservable()
            .subscribe { (event) in
            print("event : \(event)")    //event : next(())
        }.addDisposableTo(disposeBag)
        self.view.addSubview(web)

上面的代码展示了RxCocoa获取原本UIWebView,delegate的方法 并转化为 Observable。

didStartLoad 的方法在这里

    extension Reactive where Base: UIWebView {
        public var delegate: DelegateProxy {
            return RxWebViewDelegateProxy.proxyForObject(base)
        }
        public var didStartLoad: Observable<Void> {
            return delegate
                .methodInvoked(#selector(UIWebViewDelegate.webViewDidStartLoad(_:)))
                .map {_ in}
        }

原来 RxCocoa 先添加一个 DelegateProxy 类来做自己的代理。应该是用来监听原本 delegate 的回调方法的。看看 RxWebViewDelegateProxy.proxyForObject(base) 生成DelegateProxy的方法。

public protocol DelegateProxyType : AnyObject { 
	/* 一些方法列表 */
}

extension DelegateProxyType {

    public static func proxyForObject(_ object: AnyObject) -> Self {
        MainScheduler.ensureExecutingOnScheduler()

        let maybeProxy = Self.assignedProxyFor(object) as? Self

        let proxy: Self
        if let existingProxy = maybeProxy {
            proxy = existingProxy
        }
        else {
            proxy = Self.createProxyForObject(object) as! Self
            Self.assignProxy(proxy, toObject: object)
            assert(Self.assignedProxyFor(object) === proxy)
        }

        let currentDelegate: AnyObject? = Self.currentDelegateFor(object)

        if currentDelegate !== proxy {
            proxy.setForwardToDelegate(currentDelegate, retainDelegate: false)
            assert(proxy.forwardToDelegate() === currentDelegate)
            Self.setCurrentDelegate(proxy, toObject: object)
            assert(Self.currentDelegateFor(object) === proxy)
            assert(proxy.forwardToDelegate() === currentDelegate)
        }
        
        return proxy
    }
}

原来咱们的 DelegateProxy 实现了 DelegateProxyType 这个协议,得到了这个扩展方法。协议扩展中 proxy = Self.createProxyForObject(object) as! Self 就生成了一个 DelegateProxy! 之后设置这个 proxy 为 UIWebView的代理 Self.setCurrentDelegate(proxy, toObject: object) ,如果UIWebView本身已经有代理的话。将这个代理保存到 proxy.setForwardToDelegate(currentDelegate, retainDelegate: false)中。以便消息的继续传递。

再看看 DelegateProxymethodInvoked 方法

    open func methodInvoked(_ selector: Selector) -> Observable<[Any]> {
        checkSelectorIsObservable(selector)

        let subject = methodInvokedForSelector[selector]

        if let subject = subject {
            return subject
        }
        else {
            let subject = PublishSubject<[Any]>()
            methodInvokedForSelector[selector] = subject
            return subject
        }
    }

原来在 methodInvoked 方法中,为 DelegateProxy 收集了一些需要监听的 SelectormethodInvokedForSelector里。

上一步,已经将生成的DelegateProxy 变成了UIWebView的代理,当有 delegate 到消息回调时,会看这个消息是否在监听列表里,如果是的话。就把它转化成 event 通过 subject 发送出去。

RxSwift的Observer和Observable实现原理

观察者 Observer

public protocol ObserverType {
    associatedtype E
    func on(_ event: Event<E>)
}

extension ObserverType {
    public final func onNext(_ element: E) {
        on(.next(element))
    }
    public final func onCompleted() {
        on(.completed)
    }
    public final func onError(_ error: Swift.Error) {
        on(.error(error))
    }
}

作为观察者类型 ObserverType 是有能力处理next/error/completed事件的,例如UIKit所有用于展示数据的控件,他们可以绑定信号源的来时刻更新自己的数据。返回UIBindingObserver就是ObserverType类型,他们有处理next/error/completed的能力。

extension Reactive where Base: UILabel {
    public var text: UIBindingObserver<Base, String?> {
        return UIBindingObserver(UIElement: self.base) { label, text in
            label.text = text
        }
    }

被观察者 Observerable

可以被其他人订阅的。

 public protocol ObservableType : ObservableConvertibleType {
    associatedtype E
    func subscribe<O: ObserverType>(_ observer: O) -> Disposable where O.E == E
}

ObserverObservable 他们是如何连接在一起的?


class MyObserver :ObserverType{
    typealias E = Int
    func on(_ event: Event<E>){
        print(" on event : \(event)")
    }
}

Observable.of(1,2,3,4)
    .asObservable()
    .subscribe(o)
    .addDisposableTo(disposeBag)
//        on event : next(1)
//        on event : next(2)
//        on event : next(3)
//        on event : next(4)
//        on event : completed

断点停在 subscribe上可以看到

    override func subscribe<O : ObserverType>(_ observer: O) -> Disposable where O.E == Element {
        if !CurrentThreadScheduler.isScheduleRequired {
            // The returned disposable needs to release all references once it was disposed.
            let disposer = SinkDisposer()
            let sinkAndSubscription = run(observer, cancel: disposer)
            disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)

            return disposer
        }
        else {
            return CurrentThreadScheduler.instance.schedule(()) { _ in
                let disposer = SinkDisposer()
                let sinkAndSubscription = self.run(observer, cancel: disposer)
                disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)

                return disposer
            }
        }

CurrentThreadScheduler.isScheduleRequired表示当前线程的调度者CurrentThreadScheduler需要调度任务。 一般最开始用户订阅情况下,isScheduleRequired是YES,所以这里会走下面,意思是当前线程的调度者订阅一个 可执行的 block ,这个 block 的作用是将 1,2,3,4 这一组事件生产一个ScheduledItem到自己的调度队列 queue上。等待派发。

    public func schedule<StateType>(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable {
        if CurrentThreadScheduler.isScheduleRequired {
            CurrentThreadScheduler.isScheduleRequired = false

            let disposable = action(state)   //这里就是开始向队列queue中添加*ScheduledItem*

            defer {
                CurrentThreadScheduler.isScheduleRequired = true
                CurrentThreadScheduler.queue = nil
            }

            guard let queue = CurrentThreadScheduler.queue else {
                return disposable
            }

            while let latest = queue.value.dequeue() { //这里就是从队列queue中取出*ScheduledItem*,依次派发
                if latest.isDisposed {
                    continue
                }
                latest.invoke()
            }

            return disposable
        }

        let existingQueue = CurrentThreadScheduler.queue

        let queue: RxMutableBox<Queue<ScheduledItemType>>
        if let existingQueue = existingQueue {
            queue = existingQueue
        }
        else {
            queue = RxMutableBox(Queue<ScheduledItemType>(capacity: 1))
            CurrentThreadScheduler.queue = queue
        }

        let scheduledItem = ScheduledItem(action: action, state: state)
        queue.value.enqueue(scheduledItem)

        return scheduledItem
    }

//待续。。。。

DisposeBag 内存回收如何实现的呢?

RxSwift中 内存资源的回收全都靠一个。DisposeBag() 他就像一个垃圾袋儿。将RxSwift每次发生订阅事件 subscribe 时产生的 Disposable 都放到DisposeBag()里。在这个垃圾袋儿释放时,RxSwift链式调用所产生的资源将全都一起释放,请看代码。

public final class DisposeBag: DisposeBase {
        
    // state
    private var _disposables = [Disposable]() // 垃圾

    private func dispose() {  // deinit 时候就执行所有垃圾的清理方法
        let oldDisposables = _dispose()

        for disposable in oldDisposables {
            disposable.dispose()
        }
    }
    
    deinit {
        dispose()
    }
}

产生资源的方法都会返回一个实现 Disposable 协议的对象,对这个对象执行 dispose()就释放了它所有创建的资源,包括依赖它声明周期的其他Disposable对象也会在他的dispose()里一起被释放。

public protocol Disposable {
    /// Dispose resource.
    func dispose()
}

使用经验

ObservableType类型的doOn操作

可以理解为在订阅消息的同时,监听每一个消息,onError方法监听Error消息,就会触发onError的Block

 Observable.of("🍎", "🍐", "🍊", "🍋")
        .do(onNext: { print("Intercepted:", $0) }, onError: { print("Intercepted error:", $0) }, onCompleted: { print("Completed")  })
        .subscribe(onNext: { print($0) })
        .disposed(by: disposeBag)

RxSwift 里 map 和 flatMap?

先看看Swift里面两个函数的作用:

let arrayNested = [[1,2,3,4,5],[6,7]]

let maped2 = arrayNested.map { $0 }
print(maped2) // [[1, 2, 3, 4, 5], [6, 7]]

let flaped2 = arrayNested.flatMap { $0 }
print(flaped2) // [1, 2, 3, 4, 5, 6, 7]

flatMap 能将二维数组展开成一维数组。也就是 降维

flatMap 调用一次只能展开一层,也就是说,假如三维数组时调用一次flatMap会变为二维数组,调用两次才会变为一维数组

RxSwift中 也是同样的类似的概念.

    let b = Observable.of( Observable.of("🐶", "🐱"),
                           Observable.of("🐭", "🐹"))
    
        b.map{ $0 }
        .subscribe(onNext: { element in
            print(element)
            //RxSwift.ObservableSequence<Swift.Array<Swift.String>>
            //RxSwift.ObservableSequence<Swift.Array<Swift.String>>
        })
        .disposed(by: disposeBag)

        b.flatMap{ $0 }
        .subscribe(onNext: { element in
            print(element)
            //🐶
            //🐱
            //🐭
            //🐹
        })
        .disposed(by: disposeBag)

举一个实际应用的例子

button
    .rx
    .tap
    .map { URL(string: "http://httpbin/org")! }
    .flatMap(URLSession.shared.rx.JSON)
    .subscribe { event in
        switch event {
        // ...
        }
    }
    .addDisposableTo(disposeBag)
    

可以理解为

Observable<Void> -> Observable<Foundation.URL> -> Observable<Observable<jsonData>>  

这样的转换。 需要注意的是 第一map传入的闭包返回的是 URL

 	{ _ -> URL in 
		retrun URL(string: "http://httpbin/org")! 
	}

而第二步flatMap传入的闭包返回的是 Observable<jsonData>

public func json(url: Foundation.URL) -> Observable<jsonData> {
    return json(request: URLRequest(url: url))
}

Rxswift 中 Observable 和 Swift 的 [] 数组 很像。

Swift 的 flatMap 可以使 [[1,2,3,4,5],[6,7]] -> [1,2,3,4,5,6,7]

Rxswift 的 flatMap 可以使 Observable<Observable> -> Observable

还可以理解为 第二个映射 (map/flatmap 都可以理解为映射) 是一个升维的过程 (从一维变二维) 需要用flatmap函数将这个升起的维度降回来,拿到咱们真正要想要的 *Observable* 当不知道用map和flatmap哪一个时,考虑下现在的维度是不是你想要的。Rxswift里 *Value -> Observable* 这样的过程都是升维的。

此外 flatMap 还有两个兄弟方法,flatMapFirst flatMapLatest ,比如在网络请求未完成时,再次点击了 Button ,flatMapFirst 会忽略第二次点击 Button 的事件,不会进行网络请求;而 flatMapLatest 会取消第一次的网络请求,以第二次的网络请求覆盖掉。

参考

用Observable还是Driver

Driver 优势在使代码明显在主线程完成,相对切换线程就比较麻烦。

Driver vs Observable

RxSwift中的错误机制

RxSwift中,多属于异步调用API,建议用范型枚举将错误和正确的结果包装起来传递下去。

enum Result<T> {
    case value(T)
    case error(ErrorProtocol)
}

provider.request(GitHubAPI.Authorize)
    .map { result -> Result<String> in
        switch result {
        case .value(let value):
            return Result.value(value["token"].stringValue)
        case .error(let error):
            return Result.error(error)
        }
    }
    .flatMap { result -> Observable<Result<JSON>> in
        switch result {
        case .value(let token):
            return provider.request(GitHubAPI.AccessToken(code: token))
        case .error(let error):
            return Observable.just(Result.error(error))
        }
    }
    .subscribeNext { json in
        // ...
    }

总结

RxSwift 函数式编程:函数式思维,其实就是组合子逻辑,用简单的几个函数组合来构建复杂逻辑,始终以高阶的角度去表达问题,而非依赖副作用。严格意义上的函数式编程意味着不使用可变的变量,赋值,循环和其他命令式控制结构进行编程。 ReactiveX是Reactive Extensions的缩写,一般简写为Rx 。Rx是一个编程模型,目标是提供一致的编程接口,帮助开发者更方便的处理异步数据流

Rx的Observable模型让你可以像使用集合数据一样操作异步事件流,对异步事件流使用各种简单、可组合的操作。

过滤(filter)、选择(select)、变换(transform)、结合(combine)和组合(compose)多个Observable

性能上-高阶数据算法 可以讲任务分成小块儿 利用多核运算 性能快 。 安全上-因为不修改参数值,所以是线程安全 因为都是值类型 输入一样输出就一样 思想上-用简单的几个函数组合来构成复杂的逻辑,始终以高价的角度去表达问题,而非依赖副作用,异步操作primose

自我总结的函数式编程: 像以前服务器的api不是Restful风格一样,其实操作数据的方式可以抽象归纳为几种比如:增删改查就够了。而函数式编程则是把抽象归纳操作数据的几种方法 比如:Map 转换 Reduce 迭代 filter 筛选 connect 连接 combine 组合 等方法,具体的实现都用block封装起来,

Wiki 百科: 它将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象。函数编程语言最重要的基础是λ演算(lambda calculus)。而且λ演算的函数可以接受函数当作输入(引数)和输出(传出值)。

Post Directory