68826


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

[code]

    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)")
                }
            }
        }
    
    }
    
[/code]

**SceneDelegate.swift**

[code]

    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()
        }
    
    
    }
    
[/code]

**-エラー内容-**

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

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

[code]

    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)"
    
[/code]

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

[code]

    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) 
    
[/code]

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


CC BY-SA 4.0
2020-07-22T08:41:08.593
68823
2020-07-22T10:02:08.597
2020-07-22T08:56:16.593
36446
36446
question
swift
起動するStoryboardを変更しようとすると、「Thread 1: Exception: "Could not find a storyboard named 'Main' in bundle NSBundle」というエラーが出る


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

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

# こんな時の調べ方から

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

[![検索ナビゲータにMainを入力してみる](https://i.stack.imgur.com/ll7nL.png)](https://i.stack.imgur.com/ll7nL.png)

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

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

[![Info.plistの中に残っているMain](https://i.stack.imgur.com/4d8L9.png)](https://i.stack.imgur.com/4d8L9.png)

# 後は修正

Info.plist中の`Main`を`TestViewController`に修正します。

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

* * *

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


CC BY-SA 4.0
2020-07-22T10:02:08.597
68826
2020-07-22T10:02:08.597
13972
68823
answer