Xcode11の新規プロジェクト作成につまずいた

# はじめに
Xcode11 で新規にプロジェクトを作成し、iOS13 未満もサポートしようとすると大量のエラーが出てしまいます:dizzy_face:

<img width="200" alt="error" src="https://user-images.githubusercontent.com/34936885/71131158-438bc300-2237-11ea-8cdf-b392e99ab77e.png">

この辺りめんどくさくて最近作ったやつ（下記とか）は大抵 iOS13 以上サポートにしてましたが iOS13 未満もサポートするため調べてみました。

* [iOSのおしゃれな文字入力ライブラリつくってみた(swift)](https://qiita.com/am10/items/5c912c1fe723f816ee9e)
* [Swiftではじめる日本語プログラミング](https://qiita.com/am10/items/34281848c3c848659043)

# 対応
## SwiftUI を使わない
とりあえず新規作成時に User Interface で SwiftUI ではなく Storyboard を選択する。

<img width="350" alt="ui" src="https://user-images.githubusercontent.com/34936885/71131178-50101b80-2237-11ea-981e-672955d4606e.png">

頑張ってバージョンで分岐させてもいいがおとなしく今のところは SwiftUI をあきらめる:poop:

## SceneDelegate 対応
出てるエラーを見てもらうとわかる通り SceneDelegate に関連するものばかりです。  
SceneDelegate とはなんぞや？というのは下記参考

* [iOS 13 から導入されるSceneDelegateとは](https://tech.yappli.io/entry/scenedelegate)
* [iOS13のSceneDelegate周りのアプリの起動シーケンス](https://qiita.com/omochimetaru/items/31df103ef98a9d84ae6b)

対応としては下記２パターンです。

1. SceneDelegate を削除する
2. エラーに１つずつ対応する

### SceneDelegate を削除する
SceneDelegate はどうやら必須ではないらしいので削除しても大丈夫です。  
※機能が制限されるのでそことの兼ね合い

1. Info.plist の `Application Scene Manifest` キーを削除する  
`Application Scene Manifest` キーがある場合に必須となるのでこれを削除する。  
<img width="400" alt="plist" src="https://user-images.githubusercontent.com/34936885/71131197-5acab080-2237-11ea-80ad-66796be5e8c9.png">
2. SceneDelegate.swift を削除する

さあビルドっとやるとまだエラーが出る:scream_cat:

<img width="500" alt="error_2" src="https://user-images.githubusercontent.com/34936885/71131222-67e79f80-2237-11ea-9761-50d28b13e034.png">

ごっそり削除

```swift:AppDelegate.swift
import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    return true
  }
}
```

ビルド！！！  
画面が真っ黒でこんなエラーが  

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

とりあえず window を追加！！

```swift:AppDelegate.swift
import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

  var window: UIWindow? // これ追加
  
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    return true
  }
}
```

ビルド！！！！  
iOS12 でも動いた:tada:

### エラーに１つずつ対応する
エラーをみていくと全部 `@available(iOS 13.0, *)` をつけろ！っていうやつです。
下記のように `@available(iOS 13.0, *)` をつけて削除の時と同様に window を追加します。

```swift:SceneDelegate.swift
@available(iOS 13.0, *) // ここ追加
class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?


    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        guard let _ = (scene as? UIWindowScene) else { return }
    }
  :
  :
  :
```

```swift:AppDelegate.swift
import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

  var window: UIWindow? // これ追加
  
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    return true
  }
  
  // MARK: UISceneSession Lifecycle
  @available(iOS 13.0, *) // ここ追加
  func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    // Called when a new scene session is being created.
    // Use this method to select a configuration to create the new scene with.
    return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
  }

  @available(iOS 13.0, *) // ここ追加
  func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
    // Called when the user discards a scene session.
    // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
    // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
  }
}
```

2019/12/21追記。コメントでもっとクールな書き方を教えていただきました:heart_eyes:

```swift:AppDelegate.swift
import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

  var window: UIWindow? // これ追加
  
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    return true
  }
}

// MARK: UISceneSession Lifecycle
@available(iOS 13.0, *) // ここ追加
extension AppDelegate {
  func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    // Called when a new scene session is being created.
    // Use this method to select a configuration to create the new scene with.
    return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
  }

  func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
    // Called when the user discards a scene session.
    // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
    // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
  }
}
```

ビルド！！！！！  
iOS12 でも動いた:tada::tada:

SceneDelegate があると AppDelegate と両方に処理を書かないといけなくなるので ~~許してくれるなら（お客さんが）削除でいいんじゃないかなと思います:unamused:~~  
2019/12/21追記。
こちらもコメントいただきました。iOS14 などで今後 AppDelegate の処理が SceneDelegate に移行する可能性もあるのでしっかりバージョンを切り分けて対応した方が無難とのこと:frowning2:（iPhone なら Scene とか関係ないし削除しても...でも結局今後どう変わるかわからないし...）  
なのでできるならちゃんと対応しましょう！！！


なんどもこの作業をやるのがめんどくさい場合は[テンプレート機能](https://qiita.com/snoozelag/items/9fdc9128dc71b6f39171)とかあるらしいです（...知らなかった:see_no_evil:）

# さいごに
なんとかまにあった...:mask:  
（半角スペース２個で改行できるの知らなかった:speak_no_evil:）

# 参考
* [iOSのおしゃれな文字入力ライブラリつくってみた(swift)](https://qiita.com/am10/items/5c912c1fe723f816ee9e)
* [Swiftではじめる日本語プログラミング](https://qiita.com/am10/items/34281848c3c848659043)
* [Xcode11で古いプロジェクトテンプレートを利用する](https://qiita.com/snoozelag/items/9fdc9128dc71b6f39171)