Xcode11で作成したプロジェクトからSceneに関する機能をオミットする


Xcode11とUISceneとUIWindowにまつわるトラブルシュートに追われている。
個別のケースに分解してお届け。

背景

Xcode10で作成したプロジェクトをXcode11で開いた場合と、Xcode11で作成したプロジェクトで UIWindowの振る舞いが異なった。この違いはプロジェクトがScene Based Lifecycleに対応しているかどうかに左右されることが分かった。

対応

簡単に言うと以下を実施すればよい。

  • AppDelegatewindowを生やす
  • Info.plistからSceneに関する項目を取り除く
  • AppDelegateからSceneに関する項目を取り除く

これにより、iOS13で動かしてもAppDelegateを基本としたアプリのように動作する。(View Hierarchyを見るとUISceneは健在なので、互換性を保っているだけっぽい)

AppDelegatewindowを生やす

Sceneに関連する物事をオミットしたあと、AppDelegateにwindowプロパティが無いとブラックアウトしてしまうので、生やす。

// AppDelegate.swift
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
}
// AppDelegate.h
@interface AppDelegate: UIResponder <UIApplicationDelegate>

@property (nonatomic, strong) UIWindow *window;

@end

Info.plistからSceneに関する項目を取り除く

Info.plist から [Application Scene Manifest] の項目を取り除く。

ここまでの対応だけだと、iOS13でアプリを実行した場合に表示すべきStoryboardの情報が見つけられずブラックアウトする。

AppDelegateからSceneに関する項目を取り除く

AppDelegateから、Scene Based Lifecycleに関するメソッドを取り除くことで、オミットが達成される。

具体的には、以下を取り除けば良い。

  • AppDelegate application:configurationForConnectionSceneSession:
  • AppDelegate application:didDiscardSceneSessions: