Deprecate @UIApplicationMain and @NSApplicationMain
01 何が問題だったのか
iOSアプリの @UIApplicationMain や macOSアプリの @NSApplicationMain は、アプリのエントリポイントを自動生成するためにUIKitやAppKitごとに用意された属性でした。これらは、UIApplicationDelegate や NSApplicationDelegate に適合したクラスに付けておけば、コンパイラ側でプラットフォーム固有の main を合成してくれる、というものです。
しかし、SE-0281 で汎用の @main 属性が導入され、状況が変わりました。UIKit・AppKit は @main に完全対応しており、デリゲートプロトコルに適合するだけで main エントリポイントのデフォルト実装が提供されます。結果として、アプリ作者はエントリポイントの宣言方法として、
- フレームワーク固有の
@UIApplicationMain/@NSApplicationMainを使う - 汎用の
@mainを使う
という機能的に等価な2つの選択肢を前にすることになり、言語上の重複として冗長で紛らわしい状態になっていました。Xcode 14以降のテンプレートも既に @main を使っており、フレームワーク固有の属性を残し続ける意義は薄れていました。
02 どのように解決されるのか
@UIApplicationMain と @NSApplicationMain を非推奨(deprecated)とし、@main への移行を促します。具体的には、Swift 5系の言語モードでは警告、Swift 6以降の言語モードではエラーとなります。警告と同時にfix-itが提供され、属性を @main に書き換えるだけで移行が完了します。
@UIApplicationMain // warning: '@UIApplicationMain' is deprecated in Swift 5
// fixit: Change `@UIApplicationMain` to `@main`
final class MyApplication: UIResponder, UIApplicationDelegate {
/* ... */
}
fix-itを適用した結果は次のようになります。
@main
final class MyApplication: UIResponder, UIApplicationDelegate {
/* ... */
}
UIApplicationDelegate や NSApplicationDelegate には main エントリポイントのデフォルト実装があり、@main を付けたクラスがそれらのプロトコルに適合していれば、フレームワーク固有の属性を使ったときと実行時の挙動は同じになります。そのため、属性を書き換える以外のソース変更は不要です。
Swift 5系で段階的に切り替えたい場合は、upcoming feature flag DeprecateApplicationMain を有効にしておくことで、Swift 6を待たずに早めに診断を受けられます。
なお、@NSApplicationMain の挙動・移行手順は @UIApplicationMain とまったく同じです。