iOS 13 适配那些事
iOS 13 如期而至,虽然正式版还没出来,但是适配工作可以开展起来啦。在适配 iOS 13 过程中,遇到了如下一些问题。
1. UITextField 的私有属性 _placeholderLabel 被禁止访问了
遇到的第一个崩溃是修改UITextField
的placeholder
的颜色,历史遗留代码如下:
[_textField setValue:self.placeholderColor forKeyPath:@"_placeholderLabel.textColor"];
收到的错误信息⚠️
'Access to UITextField's _placeholderLabel ivar is prohibited. This is an application bug'
那么这个问题如何处理呢?
其实,UITextField
有个attributedPlaceholder
的属性,我们可以自定义这个富文本来达到我们需要的结果。
修改如下:
NSMutableAttributedString *placeholderString = [[NSMutableAttributedString alloc] initWithString:placeholder attributes:@{NSForegroundColorAttributeName : self.placeholderColor}];
_textField.attributedPlaceholder = placeholderString;
2. 控制器的 modalPresentationStyle 默认值变了
对于这个变化,有点措手不及,直接修改了模态窗口的交互。
查阅了下 UIModalPresentationStyle
枚举定义,赫然发现iOS 13
新加了一个枚举值:
typedef NS_ENUM(NSInteger, UIModalPresentationStyle) {
UIModalPresentationFullScreen = 0,
UIModalPresentationPageSheet API_AVAILABLE(ios(3.2)) API_UNAVAILABLE(tvos),
UIModalPresentationFormSheet API_AVAILABLE(ios(3.2)) API_UNAVAILABLE(tvos),
UIModalPresentationCurrentContext API_AVAILABLE(ios(3.2)),
UIModalPresentationCustom API_AVAILABLE(ios(7.0)),
UIModalPresentationOverFullScreen API_AVAILABLE(ios(8.0)),
UIModalPresentationOverCurrentContext API_AVAILABLE(ios(8.0)),
UIModalPresentationPopover API_AVAILABLE(ios(8.0)) API_UNAVAILABLE(tvos),
UIModalPresentationBlurOverFullScreen API_AVAILABLE(tvos(11.0)) API_UNAVAILABLE(ios) API_UNAVAILABLE(watchos),
UIModalPresentationNone API_AVAILABLE(ios(7.0)) = -1,
UIModalPresentationAutomatic API_AVAILABLE(ios(13.0)) = -2,
};
是的,就是UIModalPresentationAutomatic
,苹果居然直接将modalPresentationStyle
默认值改成这个,有点不解,难道是怕我们不知道新加了这个交互?这个也完全违反了开闭原则吧😒。
如何修改:
如果你完全接受苹果的这个默认效果,那就不需要去修改任何代码。
如果,你原来就比较细心,已经设置了modalPresentationStyle
的值,那你也不会有这个影响。
对于想要找回原来默认交互的同学,直接设置如下即可:
self.modalPresentationStyle = UIModalPresentationOverFullScreen;
注意:UIModalPresentationOverFullScreen
最低支持iOS 8
,如果你还要支持iOS 8
以下版本,那么你可以用UIModalPresentationFullScreen
,这个两个值的交互略有些细微差别,具体的可以自己看下效果。
3. MPMoviePlayerController 在iOS 13已经不能用了
在使用到MPMoviePlayerController
的地方,直接抛了异常:
'MPMoviePlayerController is no longer available. Use AVPlayerViewController in AVKit.'
如何修改:
这个没啥好说的,既然不能再用了,那只能换掉了。替代方案就是AVKit
里面的那套播放器。
4. iOS 13 DeviceToken有变化
可能大多数使用第三方推送的童鞋都不会注意到这个问题,一般现在的第三方推送都是将DeviceToken
原始数据丢进去,具体的解析都是第三方内部处理,所以,这些第三方解析DeviceToken
的方式正确的话,那就毫无问题。如果你们是通过这种方式来获取DeviceToken
,那你需要注意了。(这个坑也是多年前埋下的,很多文章介绍的也是下面这个方法,不规范的做法迟早要还的🤣),如下:
NSString *dt = [deviceToken description];
dt = [dt stringByReplacingOccurrencesOfString: @"<" withString: @""];
dt = [dt stringByReplacingOccurrencesOfString: @">" withString: @""];
dt = [dt stringByReplacingOccurrencesOfString: @" " withString: @""];
这段代码运行在 iOS 13 上已经无法获取到准确的DeviceToken
字符串了,iOS 13 通过[deviceToken description]
获取到的内容已经变了。
{length = 32, bytes = 0x778a7995 29f32fb6 74ba8167 b6bddb4e ... b4d6b95f 65ac4587 }
可以看到,跟原来我们认识的那个已经完全不一样了。其实,造成这样的问题,主要还是没有使用正确的方式来操作,下面是解决办法:
NSMutableString *deviceTokenString = [NSMutableString string];
const char *bytes = deviceToken.bytes;
NSInteger count = deviceToken.length;
for (int i = 0; i < count; i++) {
[deviceTokenString appendFormat:@"%02x", bytes[i]&0x000000FF];
}
未完,持续更新