iOS 13 系统禁止通过 KVC 访问
1、UITextField
1 | UITextField *textField = [UITextField new]; |
系统的 UITextField 重写了 valueForKey: 拦截了外部的取值,实现如下:
1 | @implementation UITextField |
简单解决:
去掉下划线即可 [textField valueForKey:@"placeholderLabel"];
2、UISearchBar
1 | UISearchBar *bar = [UISearchBar new]; |
根据 KVC 的实现,会先去找名为 set_cancelButtonText 的方法,所以系统内部重写了这个方法,什么事都不干,专门用来拦截 KVC,实现如下:
1 | - (void)set_cancelButtonText:(NSString *)text { |
拦截 _searchField:
1 | - (void)_searchField { |
简单解决:
直接调用 _setCancelButtonText, searchField
根据上面提到的原理,这里提供一种全局绕过这个禁止的方法供参考。
请注意:这只是一种临时的参考方案,我们 不推荐 开发者这么做, 因为访问私有属性会带来了不确定和不稳定性,少了苹果的警告会让你无节制去访问使用各种属性,随着系统的升级这私有属性会面临改动和失效的风险。
1 | @implementation NSException (DisableUIKVCAccessProhibited) |
3、推送的 deviceToken 获取到的格式发生变化
原本可以直接将 NSData 类型的 deviceToken 转换成 NSString 字符串,然后替换掉多余的符号即可:
1 | - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { |
在 iOS 13 中,这种方法已经失效,NSData类型的 deviceToken 转换成的字符串变成了:
1 | {length = 32, bytes = 0xd7f9fe34 69be14d1 fa51be22 329ac80d ... 5ad13017 b8ad0736 } |
解决方案
需要进行一次数据格式处理,友盟提供了一种做法,可以适配新旧系统:
1 | - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { |
但是注意到这种方法限定了长度,而官网文档对此方法的说明中提到,APNs device tokens are of variable length. Do not hard-code their size. ,因此可以对数据格式处理部分进行优化:
1 | - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { |