Xcode 12 新建项目兼容老系统
in 技术 with 0 comment

Xcode 12 新建项目兼容老系统

in 技术 with 0 comment

如果你使用 Xcode12 新建项目,且需要兼容 iOS13 之前的系统。那么你会获得一堆警告,并且运行在 iOS13 之前的系统上也无法看到预期的界面。

问题

因为自 Xcode12 & iOS13 以来,苹果引入了 UISceneDelegate 这个协议用于管理用户界面,且在 SceneDelegate.h 是有 window 的属性定义的。而在这之前,本来是 UIApplicationDelegate 的事情。
根据控制台日志我们也可以发现是因为 UIApplicationDelegate 没有实现 window 属性的问题:

[Application] The app delegate must implement the window property if it wants to use a main storyboard file.

如果你的项目中的 Info.plist 包含 UIMainStoryboardFile Key,则必须实现 window 属性。

解决

你只需要在 AppDelegate.h 添加如下定义即可:

@property (nonatomic, strong) UIWindow *window;

它会把 UIMainStoryboardFile 定义的 Main.storyboard 里指定的 ViewController 作为 window 的根视图。

自定义

如果想自定义 rootViewController,则在 application:didFinishLaunchingWithOptions: 方法里面添加如下代码:

if (@available(iOS 13.0, *)) {
    ///不要试图把 @available(iOS 13.0, *) 赋值到一个变量,因为 @available() 并不是一个表达式。
}else{
   ///下面自定义控制器其实在 iOS13+ 上并不会生效,但是为了不必要的对象初始化,所以做了版本判断。
   self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
   ViewController *vc = [ViewController new];
   UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:vc];
   self.window.rootViewController = nc;
   [self.window makeKeyAndVisible];
}

如果需要修改 iOS13+ 环境下的默认根控制器,则需要在 -[SceneDelegate scene:willConnectToSession:options:] 方法里面修改:

UIWindowScene *windowScene = (UIWindowScene *)scene;
self.window = [[UIWindow alloc] initWithWindowScene:windowScene];
self.window.frame = windowScene.coordinateSpace.bounds;
self.window.rootViewController = [UITabBarController new];
[self.window makeKeyAndVisible];

警告

解决 Xcode 警告就很简单了,根据 Xcode 纠正弹框,点击 Fix 即可,它会在方法后面追加 API_AVAILABLE(ios(13.0)) 申明。
xcode_warnings_fix.png

Responses