Closed7

SE-0383: Deprecated UIApplicationMain and NSApplicationMain

UeeekUeeek

Introduction

@UIApplicationMain@NSApplicationMain iOSとmacOSでそれぞれ、Appのsynthesized platform specific entory pointとして標準で使用されている。
それらの機能はSE-0281が出てから時代遅れのものとなっている。
SE-0281では、@main attributeが導入され、重複した機能として混乱を招いている。
この提案では、それらの時代をくれな代替方法を廃止することを目的としている。
Swift6からは@mainを使うようにし、UIApplicationMainなどを使用するとエラーとなる。

UeeekUeeek

Motivation

UIKitとAppKitは @main atteributeによって全体的に包まれていて、"UIApplicationDelegate"や"NSApplicationDelegate" protocolに準拠するだけで、簡単にapplicationにすることができる。
これは、現状では、アプリの作者は entorypointとしての二つの選択肢が与えられていることを意味する。そして、二つ存在することは意味がない。

  • ハードコードされたframeworkで特有のものを使う(@UIApplicationMain か @NSApplicationMain)
  • どちらのframeworkでも使える@mainを使用する。

実行時には、"application delegate protocol"に準拠したクラスについた@main attributeの挙動は、framework特有のattribute(UIApplicationMain/NSApplicationMain)と全く同じである。
entrypointの概念を表現するための方法が二つ存在することは、紛らわしい。
この提案では、@mainに entrypointの表現方法を統一することを目的とする。

UeeekUeeek

Proposed solution

pre-swift6モードでは、@UIApplicationMainとNSApplicationMainの使用はwarningになる。
warningでは、@mainで置き換えるように表示する。
Swift6では、それらの使用はerrorになる。

UeeekUeeek

Detailed design

(UIApplicationMainとNSApplicationMainの使用方法は全く同じなので、このドキュメントではUIApplicationMainについてのみ議論する。NSApplicationMainにも全く同じことが適応できる。)

Framework特有のAttributeは アプリのentrypointを宣言することでボイラプレートなコードを自動化するために、言語に導入された。
UIKitでは、entrypointはUIApplicationMainを呼ぶことになる。
この呼び出しの最後のparameterはUIApplicationDelegateを継承したクラスの名前となる。
UIKitはそのdelegateクラスを探して 起動することで、application lifecycle callbackを起動する。
それゆえ、Swiftでは UIApplicationDelegate プロトコルの準拠したクラスにこのattributeをつける必要がある。
しかし、UIApplicationDelegateへの準拠は、lifecycle callbackのため以上のことをする。
'main' entrypointの標準の実装は片方の準拠のためであるが、UIApplicationMain attributeはそれを抑制する。
これは、framework 特有のattributeを使っている既存のユーザの移行にとって重要な点となる。

この提案では、コンパイラがUIApplicationMainの使用yをみつけると、それをmainで置き換えるように提案するwarningを出すようになる。
Swift6以降では、それはエラーとなる。

@UIApplicationMain // warning: '@UIApplicationMain' is deprecated in Swift 5 
                   // fixit: Change `@UIApplicationMain` to `@main` 
final class MyApplication: UIResponder, UIApplicationDelegate {
  /**/
}

Fixitを実行すると、以下のようになる。

@main
final class MyApplication: UIResponder, UIApplicationDelegate {
  /**/
}

この簡単な移行手順は、コンパイラにUIApplicationDelegateへの準拠されたmain entrypointを選択させる。
それ以外の変更は必要ない。

UeeekUeeek

Source compatibility

既存の Libraryはビルドできるままである。なぜなら、それらはpre-Swift6モードだから。
それらでは、warningが出るだけである。

Swift6以降では、意図的に破壊的変更を引き起こし、古いattributeを使用しているとエラーとなる。
この破壊的変更は、主にapplication codeで起こる。なぜなら、ほとんどのlibraryやpackageは main entrypointを指定するframework specific attributeを使用してないからである。
新しいコードでは、templateはすでにmainを使うように変更されている。(Xcode14 or later)

UeeekUeeek

UIApplicationMainをmainに変更するだけなので、簡単。
一箇所の変更のみに見える。

このスクラップは10日前にクローズされました