AppDelegateについて調べてみる

# はじめに
ストーリーボードを使わない場合下記のようにAppDelegateにいろいろ書くと思うのだが、理解ができていないなと思ったので、あらためてドキュメントを調べてみた。

```Swift:AppDelegate
import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        self.window = UIWindow(frame: UIScreen.main.bounds)
        self.window?.rootViewController = UINavigationController(rootViewController: <表示したいViewContorollerをいれる>)
        self.window?.makeKeyAndVisible()

        return true
    }


}

```

# @UIApplicationMainとは
[Swift での main 関数の実装方法と起動時引数の扱い方](https://ez-net.jp/article/BC/vWrNTeBO/85hmtcwh9W3Y/)
によると

```
iOS アプリではmain.swift ファイルを用意しなくても、AppDelegateクラス に@UIApplicationMainディレクティブ を使うことで、main関数 を自動実装できるようになっています。
このクラスをデリゲートとして使用して初期 UI を起動するmain関数 が自動的に実装されます。
```

エントリーポイントというものを作っているらしい・・・ちょっとよくわからなかった
引き続き調査します


[Appleドキュメント　UIWindow](https://developer.apple.com/documentation/uikit/uiwindow)

# AppDelegateとは？
そもそも`AppDelegate`の理解も曖昧なのでそこから調べてみる

まず　`AppDelegate`クラスは`UIResponder`を継承 `UIApplicationDelegate`プロトコルを適合させている

下記記事を参照するとわかりやすいが、アプリの状態によって呼ばれる関数がことなることがわかる。
[【iOS】AppDelegate.swiftってなにしてんの？](https://qiita.com/SoyaTakahashi/items/cc8f48af792c353cd9f3)

## UIResponderクラス

そもそもUIResponderクラスってなんだろう
[公式ドキュメント　UIResponder](https://developer.apple.com/documentation/uikit/uiresponder)によると

```
An abstract interface for responding to and handling events.
イベントに応答して処理するための抽象インタフェース。
```

これだけだとよくわからない

```
Responder objects—that is, instances of UIResponder—constitute the event-handling backbone of a UIKit app. Many key objects are also responders, including the UIApplication object, UIViewController objects, and all UIView objects (which includes UIWindow). As events occur, UIKit dispatches them to your app's responder objects for handling.
↓
レスポンダオブジェクト、つまりUIResponderのインスタンスは、UIKitアプリのイベント処理バックボーンを構成します。
UIApplicationオブジェクト、UIViewControllerオブジェクト、すべてのUIViewオブジェクト（UIWindowを含む）など、多くの重要なオブジェクトもレスポンダです。
イベントが発生すると、UIKitはそれらを処理のためにアプリのレスポンダオブジェクトに送ります。
```

```
There are several kinds of events, including touch events, motion events, remote-control events, and press events. To handle a specific type of event, a responder must override the corresponding methods. 
↓
タッチイベント、モーションイベント、リモートコントロールイベント、プレスイベントなど、さまざまな種類のイベントがあります。
特定の種類のイベントを処理するには、レスポンダは対応するメソッドをオーバーライドする必要があります。
```

ドキュメントを読み進めていくと,`UITextField`や`UITextView`でどうやって使っているのか表記されている。

```
Responders process UIEvent objects but can also accept custom input through an input view. 
The system's keyboard is the most obvious example of an input view. 
↓
レスポンダはUIEventオブジェクトを処理しますが、入力ビューからカスタム入力を受け取ることもできます。システムのキーボードは、入力ビューの最もわかりやすい例です。
```

```
When the user taps a UITextField and UITextView object onscreen, the view becomes the first responder and displays its input view, which is the system keyboard. 
↓
ユーザーが画面上でUITextFieldオブジェクトとUITextViewオブジェクトをタップすると、
ビューが最初のレスポンダになり、その入力ビュー（システムキーボード）が表示されます。
```

```
Similarly, you can create custom input views and display them when other responders become active. 
↓
同様に、カスタム入力ビューを作成して、他のレスポンダがアクティブになったときに表示することもできます。
```

```
To associate a custom input view with a responder, assign that view to the inputView property of the responder.
↓
カスタム入力ビューをレスポンダに関連付けるには、そのビューをレスポンダのinputViewプロパティに割り当てます。
```

最後が何をいっているのかよくわからなかった・・・

`UIKit`の`UIView`の定義を調べてみると,UIViewの親クラスは`UIResponder`であることがわかる

```swift
open class UIView : UIResponder, NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace, UIFocusItem, UIFocusItemContainer, CALayerDelegate {
```

だから`UIView`を継承している`UITextField`や`UITextView`は`UIResponder`のプロパティやメソッドを使えるんですね

## プロトコルUIApplicationDelegateとは
[公式ドキュメント UIApplicationDelegate]によると(https://developer.apple.com/documentation/uikit/uiapplicationdelegate)

```
A set of methods that are called by the singleton UIApplication object in response to important events in the lifetime of your app.
↓
アプリの存続期間中の重要なイベントに応答して、シングルトンUIApplicationオブジェクトによって呼び出される一連のメソッド。
```

```
The app delegate works alongside the app object to ensure your app interacts properly with the system and with other apps.
↓
アプリデリゲートは、アプリがシステムや他のアプリと正しく対話するように、アプリオブジェクトと共に機能します。
```

```
Specifically, the methods of the app delegate give you a chance to respond to important changes. 
↓
具体的には、アプリデリゲートのメソッドによって、重要な変更に対応する機会が与えられます。
```

```
For example, you use the methods of the app delegate to respond to state transitions, such as when your app moves from foreground to background execution, and to respond to incoming notifications.
↓
たとえば、アプリデリゲートのメソッドを使用して、アプリがフォアグラウンドからバックグラウンド実行に移行したときなどの状態遷移に応答したり、着信通​​知に応答したりします。
```

```
 In many cases, the methods of the app delegate are the only way to receive these important notifications.
↓
多くの場合、アプリデリゲートのメソッドがこれらの重要な通知を受け取る唯一の方法です。
```

### application(_:didFinishLaunchingWithOptions:)とは
今回使われている関数は`UIApplicationDelegate`に含まれているメソッドの`application(_:didFinishLaunchingWithOptions:)`

[公式ドキュメント application(_:didFinishLaunchingWithOptions:)](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622921-application)によると

```
Tells the delegate that the launch process is almost done and the app is almost ready to run.
↓
起動プロセスがほぼ完了し、アプリを実行する準備がほぼ整ったことをデリゲートに伝えます。
```

１つ目の引数 application

```
●application
Your singleton app object.
```

２つ目の引数launchOptions

```
●launchOptions
A dictionary indicating the reason the app was launched (if any). The contents of this dictionary may be empty in situations where the user launched the app directly. 
For information about the possible keys in this dictionary and how to handle them, see Launch Options Keys.
↓
アプリが起動された理由を示す辞書（存在する場合）。ユーザーがアプリを直接起動した場合、この辞書の内容は空になることがあります。
この辞書で使用可能なキーとその取り扱い方法については、起動オプションキーを参照してください。
```

今まで２つ目の引数をどうやって使うのか、何が入っているのかすら意識が及んでいなかったが、どうやら第二引数には辞書でどういう経路で起動されたのかが書いてあるということを知った。

この関数は最後にBool値を返す必要がある。
だいたい初心者本には最後に`true`が書いてあってそういうものだと思っていたが、falseはどういう場合に使えばいいのかというのはドキュメントのReturn Valueに書いてあった

```
●Return Value
false if the app cannot handle the URL resource or continue a user activity, otherwise return true. 
The return value is ignored if the app is launched as a result of a remote notification.
↓
アプリがURLリソースを処理できないかユーザーアクティビティを続行できない場合はfalse、それ以外の場合はtrueを返します。
リモート通知の結果としてアプリが起動された場合、戻り値は無視されます。
```

### application(_:didFinishLaunchingWithOptions:)の中の三行について

ストーリーボードを使わない場合、お約束のように下記三行を書くという例は色んな所で見かけるが、公式ドキュメントのどこで紹介されているのか気になったので調べてみた

```Swift
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = UINavigationController(rootViewController: <表示したいViewContorollerをいれる>)
self.window?.makeKeyAndVisible()
``` 

↓場所はここだった
[Multiple Display Programming Guide for iOS](https://developer.apple.com/library/archive/documentation/WindowsViews/Conceptual/WindowAndScreenGuide/WindowScreenRolesinApp/WindowScreenRolesinApp.html#//apple_ref/doc/uid/TP40012555-CH4-SW3)

ちゃんと手順が書いてあることを確認

```
When you create a main storyboard file for your app—and identify it as the main storyboard
 in your information property list file—iOS performs several setup tasks for you. 
↓
プリケーションのメインストーリーボードファイルを作成し、
それを情報プロパティリストファイルでメインストーリーボードファイルとして識別すると、
iOSはいくつかのセットアップタスクを実行します。
```

```
●Instantiates a window.
(ウィンドウをインスタンス化します。)
●Loads the main storyboard and instantiates its initial view controller.
(メインストーリーボードをロードし、その最初のView Controllerをインスタンス化します。)
●Assigns the new view controller to the window’s rootViewController property and then makes the window visible.
(新しいView ControllerをウィンドウのrootViewControllerプロパティに割り当ててから、
ウィンドウを表示状態にします。)
```

```
In rare cases you might want to create your app’s window programmatically. You would use code something like this to programmatically create a window, install the root view controller, and make the window visible:
↓
ごくまれに、アプリのウィンドウをプログラムで作成したい場合があります。
プログラム的にウィンドウを作成し、ルートView Controllerをインストールし、ウィンドウを表示させるには、次のようなコードを使用します。
```

サンプルコードはobjective_cだけど、Swiftでも確かに同様な感じで書いている。

```objective_c
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
   UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
   myViewController = [[MyViewController alloc] init];
   window.rootViewController = myViewController;
   [window makeKeyAndVisible];
   return YES;
}

```