Xcode11以降でStoryBoardを使わずxibのみでアプリを作るメモ

storyboard嫌いマンのみんな〜〜

## 新しいプロジェクトを作る
<img width="462" alt="新しいプロジェクトを作る.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95144/248aa0cb-eec5-888f-8e58-9fe0731acc99.png">


## SingleViewAppを選ぶ
<img width="720" alt="SingleViewを選ぶ.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95144/79b395cc-1001-45d4-cb33-4a8c928cffba.png">

## とりあえずこういう設定にしとく
<img width="727" alt="とりあえずこういう設定にしておく.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95144/068ec1b9-374b-8e2f-971b-9246ca1c6a05.png">

## main.storyboardをゴミ箱に捨てる
<img width="270" alt="main.storyboardをゴミ箱に捨てる.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95144/cfb338c4-4853-3cc2-8402-f488410f7ffc.png">

## この行を消す
<img width="1138" alt="この行を消す.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95144/51aeaf14-4931-3dd5-3ed0-58a3f45352b1.png">

## この行も消す
<img width="1137" alt="この行も消す.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95144/9e530fb0-8b45-6f18-dd3c-88a044321cc6.png">

## 新しい画面を作る
<img width="729" alt="新しい画面を作る.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95144/8a7b9db4-de9c-07b8-1561-26265bccb3ce.png">

## xibにチェックをいれとくと楽
<img width="734" alt="xibにチェックを入れとくと楽.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95144/3496c52c-2a99-ecbf-a98a-96b2ab197b42.png">

## ちゃんと表示されているかどうかを確認するために適当なパーツを配置する
<img width="457" alt="ちゃんと表示されてるかを確認するために適当なパーツを配置.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95144/ddde33e3-aa0f-26ed-a66d-3710a5a2de16.png">

## つくったviewを配置する

```swift:SceneDelegate.swift
    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).
        
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = MainViewController.init()
            self.window = window
            window.makeKeyAndVisible()
        }
    }
```

## 優しいのでiOS13以前の人にも配慮する
```swift:AppDelegate.swift
@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.

        if #available(iOS 13, *) {}
        else {
            let window = UIWindow(frame: UIScreen.main.bounds)
            self.window = window
            window.rootViewController = testViewController()
            window.makeKeyAndVisible()
        }

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

    // 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: "test")
        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)")
            }
        }
    }

}
```

## おわり
![はいOK.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95144/6e87e41f-419a-b6e9-dc67-3d14e3f1106c.png)