iOS 13 下访问受限制的 _ivar

Jun 09, 2019 • 预计阅读时间 1 分钟

在 iOS 13 之前,一般是使用 KVC 来实现访问私有的实例变量,比如要访问 UITextField 的 _placeholderLabel 一般会这么做:

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'

意思很明确,就是说禁止访问 ivar,而且这是 APP 造成的 bug。
好吧,KVC 不能用了,既要适配 iOS 13 ,又要保持原有的逻辑,怎么办呢?还有 runtime 可以一试!

extension UITextField {
    var placeholderLabel: UILabel? {
        get {
            return getIvar(name: "_placeholderLabel") as? UILabel
        }
    }
}

再重新运行,APP 不再崩溃了。
getIvar 是我包装的一个扩展方法,使用 runtime 来访问 _ivar ,代码比较简单:

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 还处于仅面向开发者测试的版本,作为开发者需要踩的坑之后可能还有不少。

iOS
版权声明:如果转发请带上本文链接和注明来源。

lvv.me

iOS/macOS Developer

免费的国内 git 代码托管服务

模仿微信适配 iPad 的布局方式