LoginSignup
12
8

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-12-19

はじめに

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

error

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

対応

SwiftUI を使わない

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

ui

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

SceneDelegate 対応

出てるエラーを見てもらうとわかる通り SceneDelegate に関連するものばかりです。

SceneDelegate とはなんぞや?というのは下記参考

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

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

SceneDelegate を削除する

SceneDelegate はどうやら必須ではないらしいので削除しても大丈夫です。

※機能が制限されるのでそことの兼ね合い

  1. Info.plist の Application Scene Manifest キーを削除する
    Application Scene Manifest キーがある場合に必須となるのでこれを削除する。
    plist
  2. SceneDelegate.swift を削除する

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

error_2

ごっそり削除

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 を追加!!

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:

エラーに1つずつ対応する

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

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 }
    }
  :
  :
  :
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:

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 とか関係ないし削除しても...でも結局今後どう変わるかわからないし...)

なのでできるならちゃんと対応しましょう!!!

なんどもこの作業をやるのがめんどくさい場合はテンプレート機能とかあるらしいです(...知らなかった:see_no_evil:

さいごに

なんとかまにあった...:mask:

(半角スペース2個で改行できるの知らなかった:speak_no_evil:

参考

12
8
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
8