起因
新加入了一個(gè)項(xiàng)目碱工,翻了兩遍代碼后也沒新的需求進(jìn)來娃承,
就這么閑了幾天后,負(fù)責(zé)帶我入項(xiàng)目的老哥鬼鬼祟祟地摸到了我座位邊上...
“是不是沒活干痛垛?”
“...還草慧,還好”
“剛好第三方庫有段日子沒更新了,要不你都更到最新版本匙头,適配和測試做一下漫谷?”
“...!”
RxSwift4->5
由于是個(gè)小項(xiàng)目蹂析,本身用的第三方庫也不多舔示,API基本沒有變化碟婆,理論上是個(gè)輕松的活,
直到下面一行diff出現(xiàn)
- github "ReactiveX/RxSwift" "4.5.0"
+ github "ReactiveX/RxSwift" "5.0.1"
打開項(xiàng)目Build一下
哦嚯惕稻?竖共!
GG……
Variable被正式廢棄并打出deprecated
警告
根據(jù)RxSwift開發(fā)者的post,
Variable有以下問題
- it's not a standard cross platform concept so it's out of place in RxSwift target.
- it doesn't have an extensible counterpart for event management (PublishRelay). It models state only.
- it is naming is not consistent with *Relay
- it has an inconsistent memory management model compared to other parts of RxSwift (complete on dealloc)
大致意思是Variable不是一個(gè)跨平臺(tái)的概念俺祠,也不符合Rx的設(shè)計(jì)標(biāo)準(zhǔn)公给,因此在RxSwift的未來發(fā)展中沒有一席之地。
而RxSwift的中文文檔也提到
...許多開發(fā)者濫用 Variable蜘渣,來構(gòu)建 重度命令式 系統(tǒng)淌铐,而不是 Rx 的 聲明式 系統(tǒng)。這對于新手很常見蔫缸,并且他們無法意識(shí)到腿准,這是代碼的壞味道。...
對非科班出身程序員的我來說很難產(chǎn)生共鳴...歸納下來就是Variable被生父養(yǎng)母踢出了家門拾碌。
而很明顯的是吐葱,這個(gè)項(xiàng)目組的先人們就是上文所述的濫用Variable的開發(fā)者。
華麗麗地留下了上百條warning
Variable->BehaviorRelay
不管是warning內(nèi)容還是官方文檔都確切的注明了用BehaviorRelay來替代Variable校翔,所以沒有什么太多需要考慮弟跑。
Variable和BehaviorRelay唯一的區(qū)別是Variable被釋放時(shí)會(huì)發(fā)出一個(gè)Complete事件,而Bahavior沒有展融。
萬幸的事本項(xiàng)目沒有subscribeVariable的onComplete
的事件窖认,不需要進(jìn)行結(jié)構(gòu)性調(diào)整。
大部分改動(dòng)利用Xcode的replace功能告希,用正則表達(dá)式匹配后修改即可。
1. 修改聲明
func setTitle(_ text: Variable<String>) {
...
}
Variable<T>
需要改成BahaviorRelay<T>
很簡單烧给,把: Variable
全用: BahaviorRelay
給replace掉燕偶,解決
find: :( *)Variable
replace: :$1BehaviorRelay
2. 修改初始化方法
final class AlbumListViewModel: ViewModel {
var myAlbums = Variable<[PhotoAlbum]>([])
var memberAlbums = Variable<[PhotoAlbum]>([])
var numOfAlbum = Variable<[Int]>([])
...
}
由于聲明已經(jīng)改完了,所以不用在意(本身這個(gè)項(xiàng)目內(nèi)Variable的聲明就都是隱式的)
只需要把
var myAlbums = Variable<[PhotoAlbum]>([])
修改為
var myAlbums = BehaviorRelay<[PhotoAlbum]>(value: [])
用以下正則修改完成
find: (var|let)(.*)= Variable(.*)\((.*)\)
replace: $1$2= BehaviorRelay$3\(value: $4\)
3. 修改賦值
myAlbums.value = albumResponse.myAlbums
memberAlbums.value = albumResponse.memberAlbums
由于BehaviorRelay的value屬性為只讀础嫡,現(xiàn)在黃色的warning沒了指么,蹦出一大堆紅色的error...
應(yīng)使用BehaviorRelay的accept(:)
函數(shù)來賦新值,
將以上表達(dá)式修改為
myAlbums.accept(albumResponse.myAlbums)
(插入)
有可能出現(xiàn)換行的情況
比如
licenses.value = licenseItems.compactMap { (licenseItem) -> LicenseItem? in
...
}
正則小白的作者不知道怎么將特定結(jié)尾的字符串除外榴鼎,于是先匹配出特殊情況伯诬,手動(dòng)修改。
以下情況可能出現(xiàn)換行
find: (.*)\.value = (.*) (in|\{|\(|\.|\[)$
用正則replace一次搞定
找出規(guī)律巫财,用以下正則修改
find: (.*)\.value = (.*)$
replace: $1.accept($2)
4. 修改自增自減
var maxSelectedNum = BehaviorRelay<Int>(value: -1)
...
maxSelectedNum.value += 1
由于value
為只讀屬性盗似,需要設(shè)置一個(gè)中間變量將value
拷貝,然后修改中間變量平项。
這里新建一個(gè)文件赫舒,對BehaviorRelay進(jìn)行擴(kuò)展悍及,提供兩個(gè)新的accept函數(shù)。
// BehaviorRelay+Update.swift
import RxRelay
extension BehaviorRelay {
/// Accept update of current value
/// - Parameter update: mutate current value in closure
func acceptUpdate(byMutating update: (inout Element) -> Void) {
var newValue = value
update(&newValue)
accept(newValue)
}
/// Accept new value generated from current value
/// - Parameter update: generate new value from current, and return it
func acceptUpdate(byNewValue update: (Element) -> Element) {
accept(update(value))
}
}
然后我們就可以將原代碼修改為
maxSelectedNum.acceptUpdate(byMutating: { $0 += 1 })
// or
maxSelectedNum.acceptUpdate(byNewValue: { $0 + 1 }) //隱式return
同樣使用正則+replace一鍵搞定
find: (.*)\.value (\+|\-)= ([0-9]+)
replace: $1.acceptUpdate(byNewValue: { \$0 $2 $3 })
5. 修改泛型為數(shù)組接癌,字典等的BehaviorRelay的mutating函數(shù)
var selectedMembers = BehaviorRelay<[Member]>(value: [])
...
selectedMembers.value.append(member)
在上面的BehaviorRelay擴(kuò)展中心赶,已經(jīng)添加了acceptUpdate(byMutating:)
函數(shù),只需將上述代碼改為
selectedMembers.value.acceptUpdate(byMutating: { $0.append(member) })
即可
由于這個(gè)正則實(shí)在不好寫缺猛,全部手動(dòng)解決
6. 添加import
RxRelay
被包含在RxCocoa
module中缨叫,但沒有被包含在RxSwift
下,
而Variable
是被定義在RxSwift
中的荔燎,
所以要在需要的地方添加import RxRelay
其它
RxSwift 5的其他更新比如弯汰,throttle的參數(shù)timeInterval改成了DispatchTimeInterval
類型等,因?yàn)樵谶@個(gè)項(xiàng)目中影響較小湖雹,修改起來比較方便咏闪,在此略過不提
RxSwift5的更新可以參考這篇文章
完工!