iOS 13适配-我遇到的坑

1. Dark Mode

暗黑模式是iOS13的重要更新之一,随之而来的是我们能从系统设置中“显示与亮度”中选择“浅色”、“深色”两种模式,并且可以设置自动切换,“控制中心”亮度调节中也可直接调节。UIKit 提供新的系统颜色和 api 来适配不同颜色模式,xcassets 对素材适配也做了调整,具体适配可见: Implementing Dark Mode on iOS

如果不想适配深色模式,可以这样设置

  • 1、直接在项目的 plist 文件中设置
UIUserInterfaceStyle 
UIUserInterfaceStyleLight
  • 2、在每个UIViewController或者BaseViewController中设置
if (@available(iOS 13.0, *)) {
    [self setOverrideUserInterfaceStyle:UIUserInterfaceStyleLight];
} else {
     // Fallback on earlier versions
}

2.私有方法 KVC 不允许使用

在 iOS 13 中不再允许使用 valueForKeysetValue:forKey: 等方法获取或设置私有属性,虽然编译可以通过,但是在运行时会直接崩溃

// 使用的私有方法
[textField setValue:UIColor_d2 forKeyPath:@"_placeholderLabel.textColor"];
textField.placeholder = placeholderStr;

崩溃信息:

// 崩溃提示信息
*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Access to UITextField's _placeholderLabel ivar is prohibited. This is an application bug'

解决方案:

NSMutableAttributedString *placeholderString = [[NSMutableAttributedString alloc] initWithString:placeholderStr
                                                                                      attributes:@{NSForegroundColorAttributeName:UIColor_d2}];
textField.attributedPlaceholder = placeholderString;

3.推送的 deviceToken 获取到的格式发生变化

原本可以直接将 NSData 类型的 deviceToken 转换成 NSString 字符串,然后替换掉多余的符号即可:

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
    NSLog(@"deviceToken:%@", token);
}

在 iOS 13 中,这种方法已经失效,NSData 类型的 deviceToken 转换成的字符串变成了:

{length=32,bytes=0xd02daa63aade35488d1e24206f44037d...fd6b2fac80bddd2d}

需要进行一次数据格式处理,参考友盟的做法,可以适配新旧系统,获取方式如下:

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    if (![deviceToken isKindOfClass:[NSData class]]) return;
    const unsigned *tokenBytes = [deviceToken bytes];
    NSString *token = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x",
                          ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]),
                          ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]),
                          ntohl(tokenBytes[6]), ntohl(tokenBytes[7])];
    NSLog(@"deviceToken:%@", token);
}

这样就获取到正确的 deviceToken 字符串

d02daa63aade35488d1e24206f44037dce9ece7f85adf6acfd6b2fac80bddd2d

4.控制器的 modalPresentationStyle 默认值变了

在 iOS 13 UIModalPresentationStyle 枚举的定义中,苹果新加了一个枚举值:

typedef NS_ENUM(NSInteger, UIModalPresentationStyle) {
    ...
    UIModalPresentationAutomatic API_AVAILABLE(ios(13.0)) = -2,
}; 

在 iOS 13 中此枚举值直接成为了模态弹出的默认值,因此 presentViewController 方式打开视图是下滑返回的视差效果。如果你完全接受苹果的这个默认效果,那就不需要去修改任何代码。如果你原来就比较细心,已经设置了modalPresentationStyle 的值,那你也不会有这个影响。对于想要找回原来默认交互的同学,直接设置如下即可:

self.modalPresentationStyle = UIModalPresentationOverFullScreen;

5.MPMoviePlayerController 被弃用

在 iOS 9 之前播放视频可以使用 MediaPlayer.framework 中的MPMoviePlayerController类来完成,它支持本地视频和网络视频播放。但是在 iOS 9 开始被弃用,如果在 iOS 13 中继续使用的话会直接抛出异常:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'MPMoviePlayerController is no longer available. Use AVPlayerViewController in AVKit.'

解决方案是使用 AVFoundation 里的 AVPlayer

6.蓝牙权限描述

最近一次提审被拒情况,被拒原因之一就是需要添加蓝牙权限获取描述,提交以后构建显示正在处理中,等几分钟会自动消失,构建不成功,Apple发送邮件提示:

ITMS-90683: Missing Purpose String in Info.plist - Your app's code references one or more APIs that access sensitive user data. The app's Info.plist file should contain a NSBluetoothAlwaysUsageDescription key with a user-facing purpose string explaining clearly and completely why your app needs the data. Starting Spring 2019, all apps submitted to the App Store that access user data are required to include a purpose string. If you're using external libraries or SDKs, they may reference APIs that require a purpose string. While your app might not use these APIs, a purpose string is still required. You can contact the developer of the library or SDK and request they release a version of their code that doesn't contain the APIs. Learn more (https://developer.apple.com/documentation/uikit/core_app/protecting_the_user_s_privacy).

原因是iOS13 将废弃 NSBluetoothPeripheralUsageDescription 替换为NSBluetoothAlwaysUsageDescription

解决方法,在 info.plist 中添加新字段

 NSBluetoothAlwaysUsageDescription 
App需要您的同意,才能访问蓝牙

重新上传即可

你可能感兴趣的:(iOS 13适配-我遇到的坑)