iOS最低支援版本低於iOS 13並同時使用AppDelegate以及SceneDelegate

Jimmy Chen
iOS Funny World
Published in
Oct 8, 2021

--

當我們使用Xcode 11之後的版本新建專案,Xcode會預設產生AppDelegate.swift以及SceneDelegate.swift,此時如果在建立完專案後,需要將最低支援版本改成低於iOS 13,則會看到許多錯誤:

會出現這些錯誤的原因是,在Xcode 11之後,預設新增的專案最低支援版本為iOS 13,並且新增了一個SceneDelegate.swift檔案,那實際上有什麼改變? 我們先來了解在Xcode 11及更早版本之前,AppDelegate.swift在做什麼事

AppDelegate是App啟動時最一開始載入的檔案,裡面管理著App的生命週期,例如App進入到前景,或者App被滑到背景,都會觸發這些function,而以下這個function則是在App即將啟動時,最一開始被呼叫的。

AppDelegate.swift

當App啟動完成後,會呼叫以下function,在iOS 12或更低版本時,我們可以在這個function建立我們的初始控制器,或者在這個function建立一些初始化設定,例如以下程式碼:

AppDelegate.swift

而到了Xcode 11, iOS 13之後,新增專案時AppDelegate內的管理App生命週期的function有所改變了,並且新增SceneDelegate.swift檔案,變成由SceneDelegate來管理

以下程式碼是AppDelegate.swift內將管理App生命週期事件交給SceneDelegate管理的程式碼:

那如果想要在Xcode 11建立新專案之後,最低支援版本又低於iOS 13,怎麼辦呢?

我看網路上有許多教學是直接刪除SceneDelegate,全部交由AppDelegate來管理,但是考慮到之後有可能會有多場景的需求,因此我不打算刪除SceneDelegate,而且刪除SceneDelegate之後,又需要去改動到Info.plist內的屬性

這邊採用的做法是判斷目前聲明哪些函示及類別是iOS 13或更高版本可用,因此需要用到#available以及@available關於兩者的差別,下次我們再寫個文章來說明,因此最終程式碼會變成以下樣子:

AppDelegate:

AppDelegate.swift內可以看到,我在application(_ :willFinishLaunchingWithOptions:)實例化一個window並設定了初始視圖控制器,並且在application(_:didFinishLaunchingWithOptions:)設定讓window顯示

並且在AppDelegate.swift內加入了App生命週期,低於iOS 13的版本就會進入這些生命週期

值得一提的是,在Xcode 11產生的AppDelegate.swift內,預設是沒有window的屬性的,所以需要自己宣告一個window

接下來是SceneDelegate.swift,由於這個類別只有iOS 13才能使用,所以我們可以大膽的直接將整個class上方宣告@available(iOS 13.0, *)

SceneDelegate.swift

SceneDelegate.swift

SceneDelegate.swift的寫法跟AppDelegate.swift其實差異不大,差別只是設定初始ViewController的地方寫在scene(_ :willConnectTo:options:)

總結:

iOS版本低於iOS 13時,程式碼的部分只會走AppDelegate.swift,並且App生命週期由AppDelegate管理

iOS版本等於或高於iOS 13時,程式碼的部分會一開始先走AppDelegate.swift,當啟動完成後,進到AppDelegate.swift內配置SceneDelegate的function,並且App生命週期由SceneDelegate.swift管理

終於寫完了~這篇的目的主要是要解決新建的專案要支援較低(低於iOS 13)版本時,AppDelegate.swift與SceneDelegate.swift共存的問題,如果有更好的方式或者我有哪裡寫錯了也歡迎留言一起討論,感謝閱讀~

--

--