我們以斗魚(yú)APP為例,總結(jié)swift3.0以及swift4.0轉(zhuǎn)換過(guò)程中遇到的問(wèn)題著榴。
一啤挎、方法重寫(xiě)問(wèn)題
1、swift 3.0在子類(lèi)中的方法重寫(xiě)
我們RecommendVC類(lèi)繼承自BaseAnchorVC炭玫,BaseAnchorVC中包含setupUI方法奈嘿,然后再子類(lèi)RecommendVC的繼承中重寫(xiě)setupUI方法,這樣是沒(méi)有問(wèn)題的吞加。
extension RecommendVC {
override func setupUI(){
//調(diào)用父類(lèi)方法
super.setupUI()
collectionView.addSubview(cycleView)
collectionView.addSubview(gameView)
//拓寬collectionView的高度
collectionView.contentInset = UIEdgeInsets(top: kCycleViewH+kGameViewH, left: 0, bottom: 0, right: 0)
}
}
2裙犹、swift4.0方法的重寫(xiě)
在swift4.0方法中不可使用這種方法重寫(xiě),否則會(huì)報(bào)錯(cuò)衔憨。如下圖所示:
由于無(wú)法重寫(xiě)方法叶圃,所以我們目前就不重寫(xiě)父類(lèi)方法,而是重新給子類(lèi)定義一個(gè)方法使用践图。
二掺冠、KVC自動(dòng)賦值問(wèn)題
1、在swift3.0中码党,我們從服務(wù)器獲取數(shù)據(jù)之后德崭,進(jìn)行字典轉(zhuǎn)模型,然后使用KVC自動(dòng)賦值揖盘。
注意:由于使用了KVC自動(dòng)賦值眉厨,在項(xiàng)目中極有可能出現(xiàn)我們模型中沒(méi)有定義的key導(dǎo)致的崩潰導(dǎo)致的崩潰,所以我們重寫(xiě)func setValue(_ value: Any?, forUndefinedKey key: String) 方法兽狭,防止崩潰憾股。
class CycleModel: NSObject {
var title : String = ""
var pic_url : String = ""
var anchor : AnchorModel?
//didSet自動(dòng)監(jiān)控值的變化,使用guard進(jìn)行檢驗(yàn)
var room :[String :Any]?{
didSet{
guard let room = room else {
return
}
anchor = AnchorModel(dict: room)
}
}
init(dict : [String : Any]) {
super.init()
setValuesForKeys(dict)
}
//防止在KVC賦值時(shí)有找不到key導(dǎo)致的崩潰
override func setValue(_ value: Any?, forUndefinedKey key: String) {}
}
2箕慧、在swift4.0中服球,直接這樣使用無(wú)效。
我們必須在屬性前添加@objc颠焦,只有這樣才能滿(mǎn)足OC的KVC賦值有咨。
class CycleModel: NSObject {
@objc var title : String = ""
@objc var pic_url : String = ""
@objc var anchor : AnchorModel?
@objc var room :[String :Any]?{
didSet{
guard let room = room else {
return
}
anchor = AnchorModel(dict: room)
}
}
init(dict : [String : Any]) {
super.init()
setValuesForKeys(dict)
}
override func setValue(_ value: Any?, forUndefinedKey key: String) {
}
}
@objc知識(shí)擴(kuò)展
- @objc 作用
1、fileprivate 或者 private 保證方法私有 能在同一個(gè)類(lèi) 或者 同一個(gè)文件(extension)中訪問(wèn)這個(gè)方法 如果定義為private 那么只能在一個(gè)類(lèi)中訪問(wèn) 不能在類(lèi)擴(kuò)展中訪問(wèn)蒸健。
2座享、允許這個(gè)函數(shù)在“運(yùn)行時(shí)”通過(guò)oc的消息機(jī)制調(diào)用。比如上面的KVC賦值屬性就必須使用@objc似忧。
三渣叛、swift中的@objc的作用
swift為靜態(tài)語(yǔ)言,每個(gè)函數(shù)在編譯期間就可以確定盯捌。因此在編譯完成后可以檢測(cè)出沒(méi)有被調(diào)用到的swift函數(shù)淳衙,優(yōu)化刪除后可以減小最后二進(jìn)制文件的大小。相較于OC是一個(gè)殺手級(jí)的特性。
那么箫攀,為什么OC沒(méi)有這個(gè)特性嫩肠牲?
那是因?yàn)镺C是動(dòng)態(tài)語(yǔ)言,調(diào)用函數(shù)是在運(yùn)行時(shí)通過(guò)發(fā)送消息調(diào)用的靴跛。所以在編譯期并不知道這個(gè)函數(shù)是否調(diào)用到缀雳,所以全部的方法都會(huì)保留。
- 混合開(kāi)發(fā)中的問(wèn)題
swift中的函數(shù)怎么知道是否被OC調(diào)用了呢梢睛?
出于安全起見(jiàn)肥印,只能保留所有有可能會(huì)被OC調(diào)用的swift函數(shù),然后標(biāo)記為@objc绝葡。
在 swift 3 中除了手動(dòng)添加 @objc 聲明函數(shù)支持 OC 調(diào)用還有另外一種方式:繼承 NSObject深碱。class 繼承了 NSObject 后,編譯器就會(huì)默認(rèn)給這個(gè)類(lèi)中的所有函數(shù)都標(biāo)記為 @objc 藏畅,支持 OC 調(diào)用敷硅。然而在實(shí)際項(xiàng)目中,一個(gè) swift 類(lèi)雖然繼承了 NSObject愉阎,但是其中還是有很多函數(shù)不會(huì)在 OC 中被調(diào)用竞膳,這里有很大的優(yōu)化空間。于是根據(jù) SE160 的建議诫硕,蘋(píng)果修改了自動(dòng)添加 @objc 的邏輯:一個(gè)繼承 NSObject 的 swift 類(lèi)不再默認(rèn)給所有函數(shù)添加 @objc。只在實(shí)現(xiàn) OC 接口和重寫(xiě) OC 方法時(shí)才自動(dòng)給函數(shù)添加 @objc 標(biāo)識(shí)刊侯。
XCode 9會(huì)在運(yùn)行過(guò)程中自行檢測(cè)類(lèi)中函數(shù)是被 OC 調(diào)用章办,然后提示添加 @objc。下圖中的 vc 是 swift 中的類(lèi)滨彻,showStatus 也是 swift 函數(shù)藕届,現(xiàn)在編譯器會(huì)提示需要手動(dòng)添加 @objc: