首發於公衆號swift
在 iOS 13 以前,通常是使用 KVC 來實現訪問私有的實例變量,好比要訪問 UITextField 的 _placeholderLabel 通常會這麼作:app
extension UITextField {
var placeholderLabel: UILabel? {
get {
return value(forKey: "_placeholderLabel") as? UILabel
}
}
}
複製代碼
一直到 iOS 12,這個方法運行的很好,可是升級到了 iOS 13,運行的時候就崩潰了:測試
*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Access to UITextField's _placeholderLabel ivar is prohibited. This is an application bug'spa
意思很明確,就是說禁止訪問 ivar,並且這是 APP 形成的 bug。3d
好吧,KVC 不能用了,既要適配 iOS 13 ,又要保持原有的邏輯,怎麼辦呢?還有 runtime 能夠一試!code
extension UITextField {
var placeholderLabel: UILabel? {
get {
return getIvar(name: "_placeholderLabel") as? UILabel
}
}
}
複製代碼
再從新運行,APP 再也不崩潰了。cdn
getIvar 是我包裝的一個擴展方法,使用 runtime 來訪問 _ivar ,代碼比較簡單:blog
extension NSObject {
func getIvar(name: String) -> Any? {
guard let _var = class_getInstanceVariable(type(of: self), name) else {
return nil
}
return object_getIvar(self, _var)
}
}
複製代碼
從這些細節變動能夠大概瞭解蘋果對於開發者的態度,官方但願開發者儘可能不要使用奇技淫巧,規規矩矩按照文檔開發就好了。開發
但是,需求不容許啊...文檔
目前 iOS 13 還處於僅面向開發者測試的版本,做爲開發者須要踩的坑以後可能還有很多。