沒想到Swift里KVC還能有坑
起因
最近看了@南峰子_老驢寫的ViewStyle。利用KVC的來簡化抽取出控件設(shè)置style的代碼,想達到一個css的效果。這個庫用swift編寫,使用起來大概這樣:
class ViewController: UIViewController {
var tableView: UITableView?
override func viewDidLoad() {
super.viewDidLoad()
tableView = UITableView(frame: self.view.bounds)
tableView!.mi_styles = self.tableViewStyle
self.view.addSubview(tableView!)
}
}
// MARK: - Table View Style
extension ViewController {
var tableViewStyle: [Property: Any] {
return [
.rowHeight: 60.0,
.separatorStyle: UITableViewCellSeparatorStyle.singleLine,
.separatorColor: UIColor.lightGray,
.backgroundView: UIView(),
.separatorInset: UIEdgeInsets(top: 10.0, left: 5.0, bottom: 3.0, right: 10.0),
.cellLayoutMarginsFollowReadableWidth: true
]
}
}
閱讀源碼后發(fā)現(xiàn)有些屬性在swift是不能直接KVC的,和OC有些區(qū)別。
Bool值:isHidden
先來看下正常的在swift中kvc的套路:
let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
view.setValue(UIColor.blue, forKey: #keyPath(UIView.backgroundColor))
在swift 3中提供了#keypath()來省去開發(fā)者直接輸入字符串的尷尬。
然而,如果這個屬性是isHidden的話運行起來就會報錯。
控制臺會輸出錯誤:
‘[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key isHidden.’
提示我們沒有isHidden這個屬性。
那為什么我們平時沒有注意到這個問題呢?
view.isHidden = true
這么寫代碼是沒問題的。
其實就是Swift團隊在升級3.0的時候keypath忘記做這個功能了。。。
你可以安慰自己這個功能在swift 2.0的時候還是好好的。
如果讀者寫過OC這個原因很容易猜到。有些單獨聲明過getter的bool值直接kvc會報錯。比如isHidden這樣:
@property (nonatomic, getter=isHidden) BOOL hidden;
UIView上確實沒有isHidden屬性,那么怎么解決呢?只能回到老路上了:
view.setValue(true, forKey: "Hidden")
Enum
KVC在設(shè)置枚舉的時候也會報錯。
錯誤提示的無效的參數(shù)類型。
因為setValue的參數(shù)類型是Any,所以這里參數(shù)可以是任意類型,沒有類型檢查。但是這畢竟是一個OC的方法,所以無法直接使用swift的類型(其實String到NSString也是有轉(zhuǎn)換的,只是編譯器幫我們做了這層轉(zhuǎn)換)。
前面直接賦值的時候是正常的,但是調(diào)用KVC方法的時候編譯器沒有幫我們轉(zhuǎn)。所以這里報錯了。
那就只能自己手動轉(zhuǎn)換了:
view.setValue(UIViewTintAdjustmentMode.automatic.rawValue, forKey: "tintAdjustmentMode")
在OC中的枚舉其實就是對應(yīng)幾個數(shù)值,這里直接取出rawValue的值就可以正常使用了。
***我有一句話想對swift說: