TransWikia.com

起動するStoryboardを変更しようとすると、「Thread 1: Exception: "Could not find a storyboard named 'Main' in bundle NSBundle」というエラーが出る

スタック・オーバーフロー Asked on November 22, 2021

Swiftで起動時に表示されるStoryboardを変更したいと思っています。

普通は、Main.storyboardが起動すると思いますが、私はTestViewController.storyboad」を最初に起動するstoryboardに設定したいです。

今までに試したことは、info.plistでMain storyboard file base nameを「TestViewController」に設定しました。
また、GeneralのDevelopment InfoでMain Interfaceの項目が「TestViewController」に設定されていることを確認しました。

この状態だけでビルドして実行のボタンを押すと、まだMain.storyboardが起動したので、Main.storyboardをプロジェクトから削除しました。
そして、AppDelegate.swiftと、SceneDelegate.swiftを以下のように設定しました。

AppDelegate.swift

import UIKit
import CoreData

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        return true
    }

    // MARK: UISceneSession Lifecycle

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

    // MARK: - Core Data stack

    lazy var persistentContainer: NSPersistentContainer = {
        /*
         The persistent container for the application. This implementation
         creates and returns a container, having loaded the store for the
         application to it. This property is optional since there are legitimate
         error conditions that could cause the creation of the store to fail.
        */
        let container = NSPersistentContainer(name: "TestApp")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                 
                /*
                 Typical reasons for an error here include:
                 * The parent directory does not exist, cannot be created, or disallows writing.
                 * The persistent store is not accessible, due to permissions or data protection when the device is locked.
                 * The device is out of space.
                 * The store could not be migrated to the current model version.
                 Check the error message to determine what the actual problem was.
                 */
                fatalError("Unresolved error (error), (error.userInfo)")
            }
        })
        return container
    }()

    // MARK: - Core Data Saving support

    func saveContext () {
        let context = persistentContainer.viewContext
        if context.hasChanges {
            do {
                try context.save()
            } catch {
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                let nserror = error as NSError
                fatalError("Unresolved error (nserror), (nserror.userInfo)")
            }
        }
    }

}

SceneDelegate.swift

import UIKit

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 }
        
        window = UIWindow(frame: UIScreen.main.bounds)
        let storyboard = UIStoryboard(name: "TestViewController", bundle: nil)
        window?.rootViewController = storyboard.instantiateInitialViewController()
        window?.makeKeyAndVisible()
    }

    func sceneDidDisconnect(_ scene: UIScene) {
        // Called as the scene is being released by the system.
        // This occurs shortly after the scene enters the background, or when its session is discarded.
        // Release any resources associated with this scene that can be re-created the next time the scene connects.
        // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
    }

    func sceneDidBecomeActive(_ scene: UIScene) {
        // Called when the scene has moved from an inactive state to an active state.
        // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
    }

    func sceneWillResignActive(_ scene: UIScene) {
        // Called when the scene will move from an active state to an inactive state.
        // This may occur due to temporary interruptions (ex. an incoming phone call).
    }

    func sceneWillEnterForeground(_ scene: UIScene) {
        // Called as the scene transitions from the background to the foreground.
        // Use this method to undo the changes made on entering the background.
    }

    func sceneDidEnterBackground(_ scene: UIScene) {
        // Called as the scene transitions from the foreground to the background.
        // Use this method to save data, release shared resources, and store enough scene-specific state information
        // to restore the scene back to its current state.

        // Save changes in the application's managed object context when the application transitions to the background.
        (UIApplication.shared.delegate as? AppDelegate)?.saveContext()
    }


}

-エラー内容-

この状態でビルドして実行すると、以下のようなエラーが出ました。

AppDelegate.swift上で表示されているエラーは以下の通りです。

Thread 1: Exception: "Could not find a storyboard named 'Main' in bundle NSBundle </private/var/containers/Bundle/Application/B8C5DF50-5623-4DCF-A104-5F3CB2E82D61/FACEMOTION3D.app> (loaded)"

コンソール上に表示されているエラーは以下の通りです。

2020-07-22 17:29:57.766217+0900 TestApp[10270:1339085] Metal GPU Frame Capture Enabled
2020-07-22 17:29:57.766370+0900 TestApp[10270:1339085] Metal API Validation Enabled
2020-07-22 17:29:58.144840+0900 TestApp[10270:1339085] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Could not find a storyboard named 'Main' in bundle NSBundle </private/var/containers/Bundle/Application/B8C5DF50-5623-4DCF-A104-5F3CB2E82D61/TestApp.app> (loaded)'
*** First throw call stack:
(0x1b3228300 0x1b2f3cc1c 0x1b74de028 0x1b6a04260 0x1b6a03b58 0x1b6a05654 0x1b736cd1c 0x1b736d320 0x1b6eefe08 0x1b848affc 0x1b84b15a0 0x1b8495ebc 0x1b84b1234 0x1038d318c 0x1038d6964 0x1b84d76c4 0x1b84d7370 0x1b84d78dc 0x1b31a3af4 0x1b31a3a48 0x1b31a31fc 0x1b319df38 0x1b319d8f4 0x1bd5b4604 0x1b7371358 0x103037184 0x1b30192dc)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

どうしたらエラーが消せますでしょうか?

One Answer

私もSceneDelegateが導入されてから、storyboardの付け替えなんかはやったことがなかったので試してみました。確かに、ご質問に記載されただけの修正(*)では、書かれている通りの実行時エラーが発生するようです。(Xcode 11.6で確認。)

(*)AppDelegate.swift と SceneDelegate.swift の修正については、必要とは思えなかったので、まずはプロジェクトテンプレートから出力されたソースを修正せずに試してみました。

こんな時の調べ方から

プロジェクトの中のどこかにMain.storyboardを参照している箇所があるわけです。Xcodeの画面左側のナビゲータ領域の検索機能を使うと、設定ファイルの中身まで検索してくれます。

検索ナビゲータにMainを入力してみる

検索バーにMainと入力すると、Info.plistの中にまだMainと記載されている部分があるようです。

ここで検索結果のMainの行をクリックするとその設定部分が開いた状態でInfo.plistが表示されます。

Info.plistの中に残っているMain

後は修正

Info.plist中のMainTestViewControllerに修正します。

後は保存実行すると、先ほどの実行時エラーは出なくなりました。


コードをいじっていないので、何か違う結果が出るかもしれませんが、お試しください。

Answered by OOPer on November 22, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP