【在 iOS 开发路上的大小事-Day02】抛弃 Storyboard 改用 Xib 来做全部的 UI 设计吧

前情提要

一般在用 Xcode 创新专案的时候,会预设使用 Main.storyboard 来作为我们设计 UI 画面的地方

但这样有个缺点,就是当你 Storyboard 上面有很多画面的时候,Storyboard 会需要比较长的时间载入,以及在开发上如果要对某个画面做动作时,有时候会很难处理,让开发效率降低
所以通常会建议改用 Xib 来做 UI 画面设计,这样每个画面、每个元件都会是一个档案
在开发上会比较好处理,开发效率也会比较高
但没有说用 Storyboard 做 UI 画面设计就不好,还是要依实际状况来做变通~

实际操作

首先先到专案设置的档案 (档名:专案名称.xcodeproj),找到「Deployment Info」

找到「Main Interface」,然後将他清空

再切到「Info.plist」,找到「Application Scene Manifest」,将其全部选项都点开
全部点开後,会看到「Storyboard Name」这一行,然後把它整行删掉,如下图

接着,再将左侧的专案档案列表里面的「ViewController.swift、Main.storyboard」这两个档案删掉

接着先建立一个资料夹,来放第一个画面的档案,我们取名为「MainVC」,然後在里面新增名为「MainVC.swift、MainVC.xib」的档案

把「Also create XIB file」打勾,就会自动产生这个 ViewController 的 xib 档案,来让我们进行 UI 画面设计,现在我们左侧的专案档案列表应该会长这样

接下来,终於要来写 Code 了~
如果你的 App 最低的系统安装版本是 iOS 13 以前的话,像是 iOS 12、iOS 11 之类的
那你要在「AppDelegate.swift 跟 SceneDelegate.swift」这两个档案加入下方的 Code
如果如果你的 App 最低的系统安装版本是 iOS 13 (含)以上的话
那就直接在「SceneDelegate.swift」这个档案加入下方的 Code

会有这样的区别是因为 SceneDelegate.swift 是只有 iOS 13 (含)以上版本才会去读这个档案,iOS 13 以下的版本则是会去读 AppDelegate.swift 这个档案

所以说,如果你要让 App 可以顺利在 iOS 13 以前跟以後的系统都可以顺利开启的话,就要在 AppDelegate.swift 跟 SceneDelegate.swift 这两个档案里都加入下方的程序码

App 最低的系统安装版本是 iOS 13 以前的话,像是 iOS 12、iOS 11 之类的↓

// AppDelegate.swift
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        let rootVC = MainVC(nibName: "MainVC", bundle: nil)
        window = UIWindow(frame: UIScreen.main.bounds)
        window?.rootViewController = rootVC
        window?.makeKeyAndVisible()
        return true
    }
    ...
}
// SceneDelegate.swift
@available(iOS 13.0, *) // 这行加在 class 上面
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        let rootVC = MainVC(nibName: "MainVC", bundle: nil)
        let navigationController = UINavigationController(rootViewController: rootVC)
        window = UIWindow(frame: windowScene.coordinateSpace.bounds)
        window?.windowScene = windowScene
        window?.rootViewController = navigationController
        window?.makeKeyAndVisible()
    }
    ...
}

App 最低的系统安装版本是 iOS 13 (含)以上的话↓

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        let rootVC = MainVC(nibName: "MainVC", bundle: nil)
        let navigationController = UINavigationController(rootViewController: rootVC)
        window = UIWindow(frame: windowScene.coordinateSpace.bounds)
        window?.windowScene = windowScene
        window?.rootViewController = navigationController
        window?.makeKeyAndVisible()
    }
    ...
}

成果


本篇的范例程序码:GitHub


<<:  【Day 2】环境建置 - 安装 VisualStudio 2019

>>:  DAY02 - 那些当年很想做但就是写不出来的Side Project...囧

Alpine Linux Porting (2.1) clock is _not_ ticking

这篇开始基本上是进入持续分析有哪些未完善的部份需要进行补足。 依照这几次的bootlog的部份分析,...

第32天~

这个的上一篇在https://ithelp.ithome.com.tw/articles/10233...

Day 28 | 状态管理-从官方范例来看如何使用BLoC

那今天我们就来使用bloc及flutter_bloc 这两个来实作范例,基本上我们在实作BLoC p...

【DAY 02】如何选择网页开发的编辑器

前言 在学程序之前当然就是要先选择好适合自己的编译器啦~ 有许许多多的网页开发工具中如何选择呢? 我...

Day3 Sideproject(作品集) from 0 to 1 -技术选择

关於技术选择 可以先决定也可以题目订了後再看要用什麽 我们因为想顺便学一些比较就业取向的技术 所以就...