初探RxSwift

demo链接

根据自己对RxSwift的理解写了一个登陆以及验证码倒计时

Observer

一个可以被观察的对象被观察者监听

Observerable

观察者 产生信号推送给订阅者

/// A type-erased `ObservableType`. 
///
/// It represents a push style sequence.
public class Observable<Element> : ObservableType {

登陆业务的整体处理逻辑为

整个业务处理流程为 创建 (账号密码输入框文字改变)的观察者 ---》 发送响应信号 ---》 筛选并合并响应信号 ===》 订阅收到相应信号并处理

首先创建账号文字改变和密码文字改变的观察者 然后通过这个序列得到一个新的账号密码是否符合规范的序列输入框改变后通知accontobseque响应 最后将两个序列信号合并条件符合后再通知loginobserver(Observer)进行响应的ui处理

  ///
        let inputaccontObserVerable = accontTextField.rx.text
        let inputpasswordObserVerable = passwordTextField.rx.text
 /**
         Returns an observable sequence that **shares a single subscription to the underlying sequence**, and immediately upon subscription replays  elements in buffer.

         This operator is equivalent to:
         * `.whileConnected`
         ```
         // Each connection will have it's own subject instance to store replay events.
         // Connections will be isolated from each another.
         source.multicast(makeSubject: { Replay.create(bufferSize: replay) }).refCount()
         ```
         * `.forever`
         ```
         // One subject will store replay events for all connections to source.
         // Connections won't be isolated from each another.
         source.multicast(Replay.create(bufferSize: replay)).refCount()
         ```

         It uses optimized versions of the operators for most common operations.

         - parameter replay: Maximum element count of the replay buffer.
         - parameter scope: Lifetime scope of sharing subject. For more information see `SubjectLifetimeScope` enum.

         - seealso: [shareReplay operator on reactivex.io](http://reactivex.io/documentation/operators/replay.html)

         - returns: An observable sequence that contains the elements of a sequence produced by multicasting the source sequence.
         */

//        shareReplay 会返回一个新的事件序列,它监听底层序列的事件,并且通知自己的订阅者们。
//        解决有多个订阅者的情况下,map会被执行多次的问题。

          // 返回一个可观察序列,该序列**共享对基础序列**的单个订阅,并在订阅后立即在缓冲区中重播元素。

          //参数replay:重放缓冲区的最大元素计数。
      //  public func share(replay: Int = default, scope: RxSwift.SubjectLifetimeScope = default) -> RxSwift.Observable<Self.E>
        let accontobseque = inputaccontObserVerable.share(replay: 1).map {
            return $0!.count == 11
        }

        /// 返回一个可观察的序列 比如 输入的信号为 1,12,123 那么将这个信号转换为 false,false,false,具体可以根据业务需求来
        let passwordseque = inputpasswordObserVerable.share(replay: 1).map {
            return $0!.count == 6
        }

  //返回username和password组合后的流
        let _ = Observable.combineLatest(accont.asObservable(), password.asObservable()) {
            return ($0, $1)
            }.bind(to: loginobserver)

extension LoginViewController {

    /// 被观察者 loginobserver
    private var loginobserver: AnyObserver<Bool> {
        return AnyObserver.init(eventHandler: { [weak self] (event) in
            if let canlogin = event.element {
                self?.loginBtn.backgroundColor = canlogin ?  UIColor.red:UIColor.gray
            }
        }).asObserver()
    }

ui逻辑整理好后处理业务逻辑新建一个LoginViewmodel

初始化方法为

 convenience  init(vc: LoginViewController) {
        self.init()
        self.ctr = vc
        setUpBindSignal()
    }

实现业务与界面的双向绑定

    var accont: Driver<String?>!
    var password: Driver<String?>!
    var msmcode: Driver<String>!
    let msmhaviorsubject = BehaviorSubject<String>.init(value: "")
    
    private func setUpBindSignal() {
        accont = (ctr.accontTextField.rx.text).asDriver()
        password = (ctr.passwordTextField.rx.text).asDriver()
        let _ = msmhaviorsubject.asDriver(onErrorJustReturn: "").drive(ctr.msmlab.rx.text) 
    }

当点击登录方法后合并账号和密码信息通过flatmaplatest返回一个观察者对象等到完成后通知绑定的业务逻辑进行登录处理

 //返回username和password组合后的流
        let _ = Observable.combineLatest(accont.asObservable(), password.asObservable()) {
            return ($0, $1)
            }.flatMapLatest { (arg0) -> Observable<Loginmodel> in
                let (user, pass) = arg0
                debugPrint("用户名:\(user!) 密码:\(pass!)")
                return self.client.login(accont: user!, password: pass!)
            }.bind(to: ctr.finishbserver)

extension LoginViewController {
    var finishbserver: AnyObserver<Loginmodel> {
        return AnyObserver.init(eventHandler: { [weak self] (event) in
            if let loginmodel = event.element {
                self?.loginstatusLab.text = loginmodel.username
            }
        }).asObserver()
    }
}

网络请求层处理到此一个完整的登录和结果展示就成功了还有一个短信验证码倒计时实现了与界面的绑定。

class NetClient: NSObject {

    func login(accont: String,password: String) -> Observable<Loginmodel> {
        return Observable<Loginmodel>.create({ (event) -> Disposable in
             sleep(2)

            let loginmodel = Loginmodel()
            loginmodel.status = "登录成功"
            loginmodel.username = "红鲤鱼与绿鲤鱼与驴"

            /// 直接向订阅者发送信号
            event.on(Event.next(loginmodel))
            event.on(Event.completed)

            //event.onNext(<#T##element: Loginmodel##Loginmodel#>)
            //event.onError(<#T##error: Error##Error#>)
            //event.onCompleted()
            /// 订阅next信号 和 err信号 还有完成信号 并进行不同的处理
            ///订阅方法为 subsrcir(onnext...,onerror:....,oncomplete:...,ondisponse:.... )

            ///subscribe(onNext: <#T##((Loginmodel) -> Void)?##((Loginmodel) -> Void)?##(Loginmodel) -> Void#>, onError: <#T##((Error) -> Void)?##((Error) -> Void)?##(Error) -> Void#>, onCompleted: <#T##(() -> Void)?##(() -> Void)?##() -> Void#>, onDisposed: <#T##(() -> Void)?##(() -> Void)?##() -> Void#>)
            return Disposables.create {

            }
        })
    }
}

map

这个方法跟数组自带的api一样map遍历一个数组通过transform处理这个数组并得到一个期望返回值的数组例如
var arr = [1,2,3,4]
let newer = arr.map<Bool>.map {
    /// 处理
}
那么newarr就是一个bool类型的数组
同理 遍历这个
public func map<R>(_ transform: @escaping (Self.E) throws -> R) -> RxSwift.Observable<R>

flatmap

flatMap, flatMapLatest 让观察者观察的东西变成动态的了. 后者是只观察最后一个值.

   let _ = Observable.combineLatest(accont.asObservable(), password.asObservable()) {
            return ($0, $1)
            }.flatMapLatest { (arg0) -> Observable<Loginmodel> in
                let (user, pass) = arg0
                debugPrint("用户名:\(user!) 密码:\(pass!)")
                return self.client.login(accont: user!, password: pass!)
            }.bind(to: ctr.finishbserver)

上述代码段将用户名和密码最后一个值进行和处理生成了一组新的observerable

Driver

driver与observerable在功能上它类似被观察者(Observable),而它本身也可以与转换成被观察者(Observable: asDriver, Driver: asObservable),他不可以发送err事件 所以一旦发生错误会有容错处理(onErrorJustReturn: "")
Driver序列不允许发出error,
Driver序列的监听只会在主线程中。
所以Driver是专为UI绑定量身打造的东西。
以下情况你可以使用Driver替换BindTo:
不能发出error;
在主线程中监听;
共享事件流;

BehaviorSubject

/// Represents a value that changes over time.
///
/// Observers can subscribe to the subject to receive the last (or initial) value and all subsequent notifications.

他既可以当做观察者也可以当做被观察者

具体可以参考Rxswift的subject

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,695评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,569评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,130评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,648评论 1 297
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,655评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,268评论 1 309
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,835评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,740评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,286评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,375评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,505评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,185评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,873评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,357评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,466评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,921评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,515评论 2 359

推荐阅读更多精彩内容