iOS13系统适配内容整理

作者:拾光

整理了一些iOS13适配需要注意的点,后续会陆续补充。

1、第三方登录

如果 APP 支持三方登陆(Facbook、Google、微信、QQ、支付宝等),就必须支持苹果登录,且要放前边.

Sign In with Apple will be available for beta testing this summer. It will be required as an option for users in apps that support third-party sign-in when it is commercially available later this year.

2、增加了黑夜模式

据说审核强制要求适配黑夜模式,未确定。

// 模式强制切换
if (darkMode) {
    if (@available(iOS 13.0, *)) {
        [UIApplication sharedApplication].keyWindow.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
    }
} else {
    if (@available(iOS 13.0, *)) {
        [UIApplication sharedApplication].keyWindow.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
    }
}

  • UIColor变为动态颜色:iOS13 之前 UIColor只能表示一种颜色,而从 iOS13 开始UIColor是一个动态的 颜色,在Light Mode和Dark Mode可以分别设置不同的颜色。
  • 更新StatusBar样式
  • 更新UIActivityIndicatorView样式
之前的 UIActivityIndicatorView 有三种 style 分别为 whiteLarge, white 和 gray,现在全部废弃。

增加两种 style 分别为 medium 和 large,指示器颜色用 color 属性修改。
  • 图片适配:原生适配,通过Assets.xcassets,选择设置不同Mode下的图片,或者读取当前mode,动态选择
  • h5页面也需要适配,参考链接:Web Content适配
  • 支持强行设置App模式 :
    当系统设置为Light Mode时,对某些App的个别页面希望一直显示Dark Mode下的样式,
    这个时候就需要强行设置当前ViewController的模式了
    self.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;【忽略dark mode,最省事的办法】
    developer pay attention
    当我们强行设置当前viewController为Dark Mode后,这个viewController下的view都是Dark Mode
    由这个ViewController present出的ViewController不会受到影响,依然跟随系统的模式
    要想一键设置App下所有的ViewController都是Dark Mode,请直接在Window上执行overrideUserInterfaceStyle
    对window.rootViewController强行设置Dark Mode也不会影响后续present出的ViewController的模式
  • dark mode 切换,监听
    Xcode <模式切换时打印log> 设置 
已知问题:
  • YYLabel 如果使用了 textLayout属性,切换模式的时候 无法自动修改layout文本的颜色
  • 内嵌WebView,需要手动修改css样式

3、MPRemoteCommandCenter 音频后台播放控制器

- (void)addTarget:(id)target action:(SEL)action; 在iOS 13中selector 一定要返回MPRemoteCommandHandlerStatus,要不然会闪退。

// Target-action style for adding handlers to commands.
// Actions receive an MPRemoteCommandEvent as the first parameter.
// Targets are not retained by addTarget:action:, and should be removed from the
// command when the target is deallocated.
//
// Your selector should return a MPRemoteCommandHandlerStatus value when
// possible. This allows the system to respond appropriately to commands that
// may not have been able to be executed in accordance with the application's
// current state.
- (void)addTarget:(id)target action:(SEL)action;
- (void)removeTarget:(id)target action:(nullable SEL)action;
- (void)removeTarget:(nullable id)target;

4、一些KVC方法设置可能会导致奔溃

iOS13 以后已经不能肆无忌惮的通过 KVC 来修改一些没有暴露出来的属性了。
如:

[self.textField setValue:self.placeholderColor forKeyPath:@"_placeholderLabel.textColor"];
可以改为
self.textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.textField.placeholder attributes:@{NSForegroundColorAttributeName: color}];

UISearchBar 的 _searchField: [searchBar valueForKey:@"_searchField"];

会出现

*** Terminating app due to uncaught exception 'NSGenericException',  reason: 'Access to xxx's _xxx ivar is prohibited. This is an application bug'

5、控制器present弹出默认交互改变

/*
 Defines the presentation style that will be used for this view controller when it is presented modally. Set this property on the view controller to be presented, not the presenter.
 If this property has been set to UIModalPresentationAutomatic, reading it will always return a concrete presentation style. By default UIViewController resolves UIModalPresentationAutomatic to UIModalPresentationPageSheet, but other system-provided view controllers may resolve UIModalPresentationAutomatic to other concrete presentation styles.
 Defaults to UIModalPresentationAutomatic on iOS starting in iOS 13.0, and UIModalPresentationFullScreen on previous versions. Defaults to UIModalPresentationFullScreen on all other platforms.
 */
@property(nonatomic,assign) UIModalPresentationStyle modalPresentationStyle API_AVAILABLE(ios(3.2));

iOS 13 的 presentViewController 默认有视差效果,模态出来的界面现在默认都下滑返回。 一些页面必须要点确认才能消失的,需要适配。如果项目中页面高度全部是屏幕尺寸,那么多出来的导航高度会出现问题。

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,
};

6、UISegmentedControl 默认样式改变

默认样式变为白底黑字,如果设置修改过颜色的话,页面需要修改

7、UITabbar 层次发生改变,无法通过设置 shadowImage去掉上面的线

可以参考 腾讯 QMUIKit 里面的实现

8、App启动过程中,部分View可能无法实时获取到frame

可能是为了优化启动速度,App 启动过程中,部分View可能无法实时获取到正确的frame

// 只有等执行完 UIViewController 的 viewDidAppear 方法以后,才能获取到正确的值,在viewDidLoad等地方 frame Size 为 0,例如:
 [[UIApplication sharedApplication] statusBarFrame];

9、之前标记为 API_DEPRECATED 废弃的部分类被移除

*** Terminating app due to uncaught exception 'NSGenericException', reason: 'UISearchDisplayController is no longer supported when linking against this version of iOS. Please migrate your application to UISearchController.'

10、[deviceToken description] 获取到的格式发生变化

iOS13 正确的获得Devicetoken的代码如下:

#include 
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    if (![deviceToken isKindOfClass:[NSData class]]) return;
    const unsigned *tokenBytes = [deviceToken bytes];
    NSString *hexToken = [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:%@",hexToken);
}

11、CNCopyCurrentNetworkInfo 变化

iOS13 以后只有开启了 Access WiFi Information capability,才能获取到 SSID 和 BSSID;
参考:CNCopyCurrentNetworkInfo

An app that fails to meet any of the above requirements receives the following return value:

- An app linked against iOS 12 or earlier receives a dictionary with pseudo-values. In this case, the SSID is Wi-Fi (or WLAN in the China region), and the BSSID is 00:00:00:00:00:00.
- An app linked against iOS 13 or later receives NULL.

12、即将废弃的 LaunchImage

从 iOS 8 的时候,苹果就引入了 LaunchScreen,我们可以设置 LaunchScreen来作为启动页。当然,现在你还可以使用LaunchImage来设置启动图。不过使用LaunchImage的话,要求我们必须提供各种屏幕尺寸的启动图,来适配各种设备,随着苹果设备尺寸越来越多,这种方式显然不够 Flexible。而使用 LaunchScreen的话,情况会变的很简单, LaunchScreen是支持AutoLayout+SizeClass的,所以适配各种屏幕都不在话下。
注意啦⚠️,从2020年4月开始,所有使⽤ iOS13 SDK的 App将必须提供 LaunchScreen,LaunchImage即将退出历史舞台。

13、其他参考链接

ChenYilong/iOS13AdaptationTips

你可能感兴趣的:(iOS13系统适配内容整理)