iOS 13 下訪問受限制的 _ivar

首發於公衆號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 還處於僅面向開發者測試的版本,做爲開發者須要踩的坑以後可能還有很多。

image
相關文章
相關標籤/搜索