1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

コードでNavigationControllerを生成したときにハマったことと、解決策

Posted at

##バージョン

・Xcode12.5.1
・Swift5
・iOS 14.5

##概要
コードでNavigationControllerを生成時、エラーは出ないがNavigationControllerが生成されなかった場合の対応について

iOS13以降でアプリの起動シーケンスが変わったのでハマったと考えらる。

##解決前のコード
AppDelegate.swiftでNavigationControllerの生成を実装

AppDelegate.swift
import UIKit
import CoreData

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    //
    var window: UIWindow?
    var navigationController: UINavigationController?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        
        // 以下navigationControllerを生成するコード
        let viewController: ViewController = ViewController()
        navigationController = UINavigationController(rootViewController: viewController)
        self.window = UIWindow(frame: UIScreen.main.bounds)
        self.window?.rootViewController = navigationController
        self.window?.makeKeyAndVisible()
        
        return true
    }
}

##実行結果
![スクリーンショット 2021-07-09 20.39.55.png]
(https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423922/3eb07141-0c8e-43dc-1c43-1388604770da.png)

※赤枠の部分からviewを階層的に見てデバッグ

上図からNavigationControllerが生成されていないことがわかる

##対処法
・iOS12以前の場合

①SceneDelegate.swiftに@available(iOS 13.0, *)を追記する

SceneDelegate.swift
import UIKit

// 追記部分
@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に@available(iOS 13.0, *)等を追記する

AppDelegate.swift
import UIKit
import CoreData

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    // 以下2行を追加
    var window: UIWindow?
    var navigationController: UINavigationController?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        
        // 以下UINavigationController生成の実装部分
        let viewController: ViewController = ViewController()
        navigationController = UINavigationController(rootViewController: viewController)
        self.window = UIWindow(frame: UIScreen.main.bounds)
        self.window?.rootViewController = navigationController
        self.window?.makeKeyAndVisible()
        
        return true
    }

// @available(iOS 13.0, *)を追記する
@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.

    }
}

・iOS13以降の場合

③SceneDelegateにUINavigationController生成のコードを実装する

SceneDelegate.swift
import UIKit

@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?
    // UINavigationController型の変数を宣言
    var navigationController: UINavigationController?

    @available(iOS 13.0, *)
    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 }
        
        // // 以下UINavigationController生成の実装部分
        let viewController: UIViewController = SampleViewController()
        navigationController = UINavigationController(rootViewController: viewController)
        self.window = UIWindow(windowScene: scene as! UIWindowScene)
        self.window?.rootViewController = navigationController
        self.window?.makeKeyAndVisible()
        
    }
            ~以下略~
}


##解決策実行後の結果
スクリーンショット 2021-07-09 20.36.55.png

UINavigationControllerの生成が確認できる

##参考にさせて頂いた記事
storyboardを使わず、Swiftでナビゲーションバーをつくる(UINavigationControllerとか)
[iOS13のSceneDelegate周りのアプリの起動シーケンス]
(https://qiita.com/omochimetaru/items/31df103ef98a9d84ae6b)
[Storyboardを使わないiOSアプリ開発]
(https://zenn.dev/kazumalab/articles/76ca59f82c189cf33d43)

##終わりに
同じようなことで困ってる人の役に立ったら幸いです!
もし間違っている部分がありましたら、ご指摘いただけると嬉しいです!

1
1
0

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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?