在 Xcode 11 開一個 iOS 12 和 13 都能跑的專案

Lumanman
6 min readNov 13, 2019

--

昨天聽完拐子在 iOS Taipei 的分享後,今天自己嘗試在 Xcode 11 開一個 iOS 12 和 13 都能跑的專案,發現還是有些坑,所以簡單記一下筆記,方便日後使用。

IDE: Xcode 11.1
Github 專案:
master branch:user interface 的設定是 SwiftUI
storyboard branch:user interface 的設定是 Storyboard

我們都知道,SwiftUI 只能在 iOS 13 的系統以上跑,但 Xcode 11 開的新專案是預設用 SwiftUI 的設定。 如果我們在 iOS 12 安裝 Xcode 11 開的專案,會收到一堆 error:

以下是怎麼在 Xcode 11 開一個 iOS 12 和 13 都能跑的專案的步驟~

如果一開始 user interface 的設定是 SwiftUI…

Step 1: 刪掉所有與 Swift UI 相關的 file 和程式碼

刪除與 SwiftUI 相關的 file ,包括 ContentView.swift 和 SceneDelegate.swift,以及 AppDelegate 中的程式碼:

Step 2: 用慣常的做法在 AppDelegate 中 init window

在 AppDelegate 中 init window:

如果我們現在把專案 build 起來,我們會發現 Info.plist 出現 error:

Step 3: 改 Info.plist 的設定

<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string 改為<string>$(PRODUCT_MODULE_NAME).AppDelegate</string.

如果我們現在把專案 build 起來,APP 會 cash, LLDB 出現以下 error 訊息:

[SceneConfiguration] Info.plist configuration “(no name)” for UIWindowSceneSessionRoleApplication contained UISceneDelegateClassName, “ProjectSupportingIOS12n13.AppDelegate”, but it does not conform to the UISceneDelegate protocol.

AppDelegate 出事了。

Step 4: 讓 AppDelegate conform UISceneDelegate protocol

直接把 UISceneDelegate 加上去後,IDE 沒有出現任何要實作 UISceneDelegate function 的提示:

如果我們現在把專案在 iOS 12.2 上跑是沒有問題的,但如果在 iOS 13.1 上跑,我們將得到一個全黑的畫面而 debug console 沒有任何錯誤:

Step 5: 用 UIWindowScene init window

雖然我們沒有看到任何錯誤,但若打開 debug view hierarchy, 我們會發現該 window 不是我們熟悉的 UIWindow,而是 UIWindowScene(瞎毀?!

所以把原本 SceneDelegate 中 init window 的 function 加到 AppDelegate,並在此 init window:

但這次樣寫 window 還是一個與 UIWindowScene 無關的 window,所以我們需要用 UIWindowScene 去 init window:

這樣這個專案在iOS 12和13上均可正常運行。

如果一開始 user interface 的設定是 Storyboard…

要做的事幾乎與上面相同,只是這邊我們只能 conform UIWindowSceneDelegate 而不能用 UISceneDelegate,並且不需要執行步驟5。

AppDelegate 只能 conform UIWindowSceneDelegate

創建的專案的時候如果使用 SwiftUI 的話,AppDelegate conform UISceneDelegate 或 UIWindowSceneDelegate 都可以。

但是,如果我們創建的專案的時候使用Storyboard,AppDelegate 只能 conform UIWindowSceneDelegate, 否則,該 window 將無法正確初始化,我們會收到以下錯誤消息:

[WindowScene] There is no scene delegate set. A scene delegate class must be specified to use a main storyboard file.

Storyboard 的默認配置與 SwiftUI 略有不同:

不需要執行步驟5

更改 Info.plist 的配置就可以,不用加額外的設定:

以上。

如果沒有要用 SwiftUI 的話,我還是會選擇用 Xcode 10.3 去開專案。(累)

--

--

Lumanman

Swift learner & sharer | Nothing is wasted, nothing is in vain.