我對(duì)這個(gè)方法的理解是:轉(zhuǎn)化現(xiàn)有的信號(hào)為我們需要的新的信號(hào)喊式,并且在信號(hào)發(fā)出start()信號(hào)時(shí)才啟動(dòng)
先來(lái)看個(gè)簡(jiǎn)單的栗子吧:
/**
由給定的信號(hào)操作符創(chuàng)建一個(gè)新的信號(hào)
*/
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的話打印出來(lái)的是100鞭缭,但是把lift加上的話,打印出來(lái)的是I have get 100
來(lái)看看lift方法中調(diào)用的transform里到底什么意思:把原有的<Int, NoError>類型的信號(hào)轉(zhuǎn)換成<String, NoError>類型的信號(hào)---
return signal.map { "I have get ($0)" }的意思是原有的信號(hào)經(jīng)過(guò)map轉(zhuǎn)變成string字符串類型头岔,并發(fā)送.
下面在寫(xiě)個(gè)例子--我把它步驟分解下肄满”倏剑看其怎么一步一步實(shí)現(xiàn)的
//創(chuàng)建轉(zhuǎn)換的類型--- Signal<[Int], NoError> -> Signal<[Int], NoError>
let transform: Signal<[Int], NoError> -> Signal<[Int], NoError> = {
//原來(lái)的信號(hào)
originalSignal in
//創(chuàng)建新的信號(hào)
let (resultSignal, resultObserver) = Signal<[Int], NoError>.pipe()
//原來(lái)的信號(hào)發(fā)送信號(hào)
originalSignal.observeNext({ originalArr in
//把原有信號(hào)中的數(shù)組中每個(gè)元素做 乘 5 再加 2 的操作,并返回一個(gè)接受此結(jié)果的新數(shù)組
let newArr = originalArr.map { $0 * 5 + 2 }
//新信號(hào)的觀察者發(fā)送信號(hào)-----最重要一定要新信號(hào)的觀察者發(fā)送信號(hào)掏缎,外界才能做出反應(yīng)
resultObserver.sendNext(newArr)
})
// 返回新的信號(hào)
return resultSignal
}
SignalProducer<[Int], NoError>(value: [1, 2, 3, 4, 5])
.lift(transform)
.startWithNext { result in
print(result)
}
打印出的結(jié)果為 [7, 12, 17, 22, 27]
下面再舉個(gè)我項(xiàng)目中有點(diǎn)麻煩的一個(gè)例子---
項(xiàng)目中需要獲取城市列表皱蹦,但是后臺(tái)給的是兩段式獲取的。眷蜈。即先獲取獲取全部的省沪哺,然后在根據(jù)省ID來(lái)獲取下面的市。但是我想要是的一個(gè)數(shù)組類型---[“省名稱”: [市]]酌儒。下面直接放代碼
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):
//這里獲取到的是全部的省--需要再進(jìn)一步獲取到全部的市
//在這里一定要?jiǎng)?chuàng)建GCD group辜妓,因?yàn)榫W(wǎng)絡(luò)請(qǐng)求是異步的,如果不加入group的話忌怎,它會(huì)先直接返回結(jié)果籍滴,然后在請(qǐng)求網(wǎng)絡(luò)
let group = dispatch_group_create()
var dict = CityDic()
provinces.forEach({ (province) in
//這里一定要在循環(huán)里面dispatch_group_enter,不能放在外面---因?yàn)橐粋€(gè)循環(huán)就是一個(gè)網(wǎng)絡(luò)請(qǐng)求
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):
//這里榴啸,無(wú)論是失敗還是成功孽惰,或者是其他什么。請(qǐng)立即退出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收到結(jié)束通知的時(shí)候勋功,在主線程里觀察者發(fā)送結(jié)果
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)
}
}
}
注:這里面用到了我之前寫(xiě)道的 一篇文章里的內(nèi)容坦报, 使用Moya+ReactiveCocoa 進(jìn)行網(wǎng)絡(luò)請(qǐng)求,那篇文章里面也用到了lift狂鞋,大家有興趣的話片择,可以去看看http://www.reibang.com/p/7bf635577900
這里面最主要的是要用GCD group~~而且是dispatch_group_enter(group) 以及dispatch_group_leave(group),不能用dispatch_group_async(dispatchGroup, dispatchQueue, ^(){ NSLog(@"dispatch-1"); });骚揍,因?yàn)樽止埽W(wǎng)絡(luò)請(qǐng)求是一個(gè)操作,但是網(wǎng)絡(luò)請(qǐng)求返回結(jié)果又是一個(gè)操作----切記切記