iOS 13 下访问受限制的 _ivar

首发于公众号

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。