美文网首页
ReactiveCocoa中lift的使用方法

ReactiveCocoa中lift的使用方法

作者: flyrr | 来源:发表于2016-10-02 10:19 被阅读91次

    我对这个方法的理解是:转化现有的信号为我们需要的新的信号,并且在信号发出start()信号时才启动

    先来看个简单的栗子吧:

        /**
         由给定的信号操作符创建一个新的信号
         */
        func liftExample() {
           let transform: Signal<Int, NoError> -> Signal<String, NoError> = {
                signal in
                return signal.map { "I have get \($0)" }
            }
            SignalProducer<Int, NoError>(value: 100)
    //        .lift(transform)
                .startWithNext { print($0) }
        }
    

    这里如果我们不加lift的话打印出来的是100,但是把lift加上的话,打印出来的是I have get 100

    来看看lift方法中调用的transform里到底什么意思:把原有的<Int, NoError>类型的信号转换成<String, NoError>类型的信号---
    return signal.map { "I have get ($0)" }的意思是原有的信号经过map转变成string字符串类型,并发送.

    下面在写个例子--我把它步骤分解下。看其怎么一步一步实现的

    //创建转换的类型--- Signal<[Int], NoError> -> Signal<[Int], NoError> 
    let transform: Signal<[Int], NoError> -> Signal<[Int], NoError> = {
          //原来的信号
                originalSignal in
             //创建新的信号
                let (resultSignal, resultObserver) = Signal<[Int], NoError>.pipe()
            //原来的信号发送信号
                originalSignal.observeNext({ originalArr in
            //把原有信号中的数组中每个元素做  乘 5 再加 2 的操作,并返回一个接受此结果的新数组
                    let newArr = originalArr.map { $0 * 5 + 2 }
             //新信号的观察者发送信号-----最重要一定要新信号的观察者发送信号,外界才能做出反应
                    resultObserver.sendNext(newArr)
                })
           // 返回新的信号
                return resultSignal
            }
            
            SignalProducer<[Int], NoError>(value: [1, 2, 3, 4, 5])
            .lift(transform)
            .startWithNext { result in
                print(result)
            }
    

    打印出的结果为 [7, 12, 17, 22, 27]

    下面再举个我项目中有点麻烦的一个例子---

    项目中需要获取城市列表,但是后台给的是两段式获取的。。即先获取获取全部的省,然后在根据省ID来获取下面的市。但是我想要是的一个数组类型---[“省名称”: [市]]。下面直接放代码

    typealias CityDic = [String: [City]]
       let cityDic = MutableProperty<CityDic>(CityDic())
    
    /**
         获取城市列表
         */
        mutating private func getCityList() {
            let transform: Signal<[City], NetRequestError> -> Signal<CityDic, NetRequestError> = {
                citysSignal in
                let (resultSignal, resultObserver) = Signal<CityDic, NetRequestError>.pipe()
                citysSignal.observe({ event in
                    switch event {
                    case let .Next(provinces):
          //这里获取到的是全部的省--需要再进一步获取到全部的市
    
                      //在这里一定要创建GCD  group,因为网络请求是异步的,如果不加入group的话,它会先直接返回结果,然后在请求网络
                        let group = dispatch_group_create()
                        var dict = CityDic()
                    provinces.forEach({ (province) in
                 //这里一定要在循环里面dispatch_group_enter,不能放在外面---因为一个循环就是一个网络请求
                        dispatch_group_enter(group)
                     NetHelper.sharedInstance.requestProvider
                     .request(RequestAPI.getCityList(type: CityType.city, parentId: province.id))
                     .mapResponseToObjArray(City)
                     .start({ event in
                        switch event {
                         case let .Next(value):
                            dict.updateValue(value, forKey: province.name!)
                            dispatch_group_leave(group)
                         case  let .Failed(error):
                       //这里,无论是失败还是成功,或者是其他什么。请立即退出group  ----dispatch_group_leave(group)
                            resultObserver.sendFailed(error)
                            dispatch_group_leave(group)
                         default:
                            dispatch_group_leave(group)
                            return
                            }
                          })
                        })
                        dispatch_group_notify(group, dispatch_get_main_queue(), {
                         //然后,在GCD group收到结束通知的时候,在主线程里观察者发送结果
                            resultObserver.sendNext(dict)
                        })
                    default:
                        break
                    }
                })
                return resultSignal
            }
            NetHelper.sharedInstance.requestProvider
            .request(RequestAPI.getCityList(type: CityType.province, parentId: nil))
            .mapResponseToObjArray(City)
            .lift(transform)
            .startWithResult { result in
                switch result {
                case let .Success(value):
                    self.cityDic.value = value
                case let .Failure(error):
                    print(error)
                }
            }
        }
    

    注:这里面用到了我之前写道的 一篇文章里的内容, 使用Moya+ReactiveCocoa 进行网络请求,那篇文章里面也用到了lift,大家有兴趣的话,可以去看看http://www.jianshu.com/p/7bf635577900

    这里面最主要的是要用GCD group~~而且是dispatch_group_enter(group) 以及dispatch_group_leave(group),不能用dispatch_group_async(dispatchGroup, dispatchQueue, ^(){ NSLog(@"dispatch-1"); });,因为,网络请求是一个操作,但是网络请求返回结果又是一个操作----切记切记

    相关文章

      网友评论

          本文标题:ReactiveCocoa中lift的使用方法

          本文链接:https://www.haomeiwen.com/subject/pnkdyttx.html