iT邦幫忙

2025 iThome 鐵人賽

DAY 5
0
生成式 AI

iOS? AI-Yes!:用 Vide Coding 加速我的 Swift 學習曲線系列 第 5

Day 5 - 專案啟動與架構解析:App 如何從無到有並開始呼吸?

  • 分享至 

  • xImage
  •  

昨天我們將開發者的「心法」與「工具箱」都準備妥當。今天,我們終於建立我們的第一個 Xcode 專案


建立專案 - 進入Swift的世界

第一步:打開Xcode新建專案

image

第二步:選擇App → 按右下角的Next

image

第三步:

  1. 輸入專案名字
  2. 先選擇Storyboard,下面會有方法把它刪除
  3. 點選Next並選擇你要放在哪個資料夾下

image

第四步:會看到下面的畫面,代表專案已經建置好了
image

專案檔案巡禮 - 認識 App 的管理團隊

當建立好專案後,第一步就是試圖理解左邊那些檔案的用途。

  • 困惑點:AppDelegate 和 SceneDelegate 這兩個檔案名字很像,它們是什麼關係?還有 Assets、LaunchScreen、Info.plist 這些,各自的功能又是什麼?

  • AI 協作

    • 我的 Prompt:我剛建立了一個新的 iOS App 專案。請像一位資深工程師帶新人一樣,為我簡單介紹 AppDelegate, SceneDelegate, ViewController, Assets.xcassets, launchScreen.storyboard, 和 Info.plist這些檔案的核心功能。

    AI 的回答

    好的,歡迎加入 iOS 開發的行列!把這些基礎檔案搞懂,是成為一位稱職 iOS 工程師的第一步。我們把它想像成一家新創公司,而你就是創辦人,我來帶你認識一下公司的核心部門與文件。

    這是在 Xcode 建立新專案後,你會在左側檔案導覽器看到的最核心的幾個檔案:


    1. AppDelegate.swift

    核心功能:應用程式生命週期管理中心 (Process-Level Events)

    把它想像成公司的「執行長 (CEO)」AppDelegate 負責處理整個 App「進程 (Process)」層級的事件。無論你的 App 有多少個畫面或視窗,整個 App 從啟動到被終止,都由它來管理。

    主要職責:

    • 應用程式啟動與終止: 處理 App 剛啟動完成 (didFinishLaunchingWithOptions) 和即將被終止 (applicationWillTerminate) 時需要執行的任務。例如:初始化第三方服務 (Firebase, Google Analytics)、設定日誌系統等。
    • 處理外部事件: 推播通知 (Push Notifications) 的註冊與接收、處理從其他 App 開啟的 URL (Deep Linking)。
    • 核心資料的設定: 在過去 (iOS 12 及更早),它也負責設定 UI,但現在這部分職責大多已移交給 SceneDelegate

    你會在什麼時候修改它?

    當你需要「在 App 一啟動時」就設定好的全域服務時,例如串接推播通知、全域的資料庫初始化。


    2. SceneDelegate.swift

    核心功能:使用者介面場景生命週期管理 (UI-Level Events)

    如果 AppDelegate 是 CEO,那 SceneDelegate 就是特定業務線的「部門主管」。從 iOS 13 開始,為了支援 iPadOS 的多視窗功能,Apple 將 UI 生命週期的管理從 AppDelegate 中獨立出來。一個 Scene 代表 App 的一個 UI 實例(一個視窗)。

    主要職責:

    • 場景的連接與斷開: 當一個新的 UI 場景(視窗)要顯示在螢幕上時 (scene(_:willConnectTo:options:)),SceneDelegate 會負責建立這個視窗 (UIWindow) 並設定它的初始畫面 (ViewController)。
    • 場景狀態轉換: 管理場景進入前景 (sceneWillEnterForeground)、變為活躍狀態 (sceneDidBecomeActive)、進入背景 (sceneDidEnterBackground) 等。
    • 多視窗管理: 在 iPad 上,每個 App 視窗都有自己對應的 SceneDelegate 實例。

    你會在什麼時候修改它?

    當 App 從背景切回前景時,你需要更新畫面資料;或是當 App 進入背景時,你需要儲存使用者的進度或暫停遊戲。這些都寫在這裡。


    3. ViewController.swift

    核心功能:單一畫面的管理者

    這就是你公司的「專案經理」或「第一線員工」。ViewController 負責管理 App 中的一個特定畫面(或稱為 View)。它是 MVC (Model-View-Controller) 設計模式中的 C。

    主要職責:

    • 管理 View 的生命週期: 從畫面被載入記憶體 (viewDidLoad)、即將顯示 (viewWillAppear)、到最後從螢幕上消失 (viewDidDisappear),都有對應的函式可以讓你掛載邏輯。
    • 處理使用者互動: 監聽按鈕點擊 (@IBAction)、處理手勢、更新畫面上的標籤 (UILabel) 或圖片 (UIImageView)。
    • 連接資料與畫面: 從 Model 層取得資料,然後將資料呈現在 View 上。

    你會在什麼時候修改它?

    這將是你最常、最主要撰寫程式碼的地方。App 的所有功能、畫面邏輯、使用者互動,絕大部分都在這裡實現。


    4. Assets.xcassets

    核心功能:資源素材庫

    這是公司的「總務部」或「素材倉庫」。所有 App 需要用到的靜態資源,都應該放在這裡統一管理。

    主要職責:

    • 圖片管理 (Images): 你可以把同一張圖的不同解析度版本 (例如 @1x, @2x, @3x) 放在同一個 Image Set 裡,系統會根據裝置的螢幕密度自動選用最適合的版本。
    • 顏色管理 (Colors): 你可以定義全域使用的顏色,並為它命名(例如 "PrimaryTextColor")。這樣在程式碼或 Storyboard 中就可以用名稱來取用,方便統一修改與管理。
    • App 圖示 (AppIcon): App 在主畫面上顯示的圖示就是在這裡設定的。

    你會在什麼時候修改它?

    當你需要為 App 新增一張圖片、一個圖示,或是一個客製化的顏色時,就來這裡操作。


    5. LaunchScreen.storyboard

    核心功能:App 啟動過渡畫面

    這是公司的「接待大廳」或「迎賓門面」。當使用者點擊 App 圖示後,在你的 App 完全準備好、第一個 ViewController 顯示出來之前,系統會先顯示這個 LaunchScreen

    主要職責:

    • 提供快速的視覺回饋: 讓使用者知道 App 已經開始啟動了。
    • 品牌展示: 通常會放上 App 的 Logo 和一個簡單的背景色。
    • 注意: 這個畫面不能執行任何程式碼,它必須是靜態的、輕量的。它的目的是盡快顯示,而不是做複雜的動畫或載入資料。

    你會在什麼時候修改它?

    通常你只會設定一次,把 Logo 和背景放好後,就很少再動它了。


    6. Info.plist

    核心功能:App 的設定檔 (Property List)

    這是公司的「工商登記證」。它是一個 XML 格式的檔案,用來儲存 App 的核心設定與元數據 (Metadata),作業系統會讀取這些資訊來了解你的 App。

    主要職責:

    • App 身份識別:
      • Bundle Identifier:App 在 App Store 上的唯一 ID。
      • Bundle Name:顯示在主畫面上的 App 名稱。
      • Bundle Version:版本號。
    • 權限請求說明: 當 App 需要使用相機、定位、聯絡人等敏感權限時,你必須在這裡提供一段文字,向使用者解釋你為什麼需要這個權限。例如 Privacy - Camera Usage Description
    • 硬體與軟體需求: 設定 App 支援的裝置方向(直向、橫向)、支援的最低 iOS 版本等。

    你會在什麼時候修改它?

    當你要發布新版本、需要請求新的系統權限、或調整 App 的基本行為時,就需要編輯這個檔案。


    大局觀:App 啟動時發生了什麼?

    簡單來說,流程是這樣的:

    1. 使用者點擊你的 App 圖示。
    2. 作業系統立刻載入 LaunchScreen.storyboard 並顯示它。
    3. 同時,系統在背景建立 App 進程,並呼叫 AppDelegate,告訴它「你被啟動了」。
    4. AppDelegate 接著要求 SceneDelegate 建立一個 UI 場景。
    5. SceneDelegate 建立一個 UIWindow,並實例化你的初始 ViewController,將其設為 window 的根視圖控制器。
    6. 當你的 ViewController 準備就緒後,系統會用它換掉 LaunchScreen,使用者就看到了 App 的主畫面。

    給新人的建議

    一開始,你 90% 的時間都會花在 ViewController.swiftMain.storyboard (或 SwiftUI View) 上。先專注於如何在這上面建立畫面和處理使用者互動。當你需要圖片時,就去 Assets.xcassets;當你需要請求權限或改 App 名稱時,才去碰 Info.plist

    隨著你開發的功能越來越複雜,例如需要處理推播通知或背景任務時,你自然就會回頭來找 AppDelegateSceneDelegate

    • 在 AI 解釋完 SceneDelegate 的職責是「設定初始畫面」後,那能不能完全不要 Storyboard,直接用程式碼告訴 SceneDelegate 要用哪個畫面當起點?

做出決定與動手改造:告別 Storyboard

我的改造步驟:

  1. 第一步:刪除 Storyboard 在專案設定中的關聯 ,找到info 裡面的storyborad Name,點選後,直接刪掉

    image
    image

  2. 第二步:移除 Build Settings 中的 Main Storyboard 設定,把UIkit Main Storyborad File Base Name點選後,按下delete,注意按下刪除後還是會保留這行。
    image

  3. 第三步:刪除專案檔案 (Main.storyboard,LanuchScreen.storyboard, ViewController.swift)

  4. 第四步:建立我們自己的 MainViewController (勾選 XIB)

    image

    image

    image

  5. 第五步:修改 SceneDelegate

    image

    把我選取起的範圍用下面的程式碼取代

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // 1. 確保場景是 UIWindowScene 的實例,否則返回。
        guard let windowScene = (scene as? UIWindowScene) else { return }
    
        // 2. 創建主視圖控制器的實例,使用 XIB 檔案來初始化它。
        let rootVC = MainViewController(nibName: "MainViewController", bundle: nil)
    
         // 3. 使用主視圖控制器創建一個導航控制器。
        let navigationController = UINavigationController(rootViewController: rootVC)
    
        // 4. 創建並設置 UIWindow 的實例,這個窗口是應用的主要顯示區域。
        window = UIWindow(frame: windowScene.coordinateSpace.bounds)
    
        // 5. 設置窗口的場景,這樣窗口就會和指定的場景關聯。
        window?.windowScene = windowScene
    
        // 6. 設置窗口的根視圖控制器為導航控制器,這樣應用的初始視圖會顯示在這個導航控制器中。
        window?.rootViewController = navigationController
    
        // 7. 使窗口顯示並成為應用的主要窗口。
        window?.makeKeyAndVisible()
    }
    

    取代完後再選取一次按右鍵,選擇Create code Snippet
    image

    可以取名為defaultSceneDelegate,這樣之後就不用一直在複製貼上了

    image

    image

  6. 第六步:修改MainViewController

    image

    把我選取起的範圍用下面的程式碼取代

    class MainViewController: UIViewController {
    
        // MARK: - IBOutlet
    
        // MARK: - Property
    
        // MARK: - LifeCycle
        override func viewDidLoad() {
            super.viewDidLoad()
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
        }
    
        override func viewIsAppearing(_ animated: Bool) {
            super.viewIsAppearing(animated)
        }
    
        override func viewWillLayoutSubviews() {
            super.viewWillLayoutSubviews()
        }
    
        override func viewDidLayoutSubviews() {
            super.viewDidLayoutSubviews()
        }
    
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
        }
    
        override func viewWillDisappear(_ animated: Bool) {
            super.viewWillDisappear(animated)
        }
    
        override func viewDidDisappear(_ animated: Bool) {
            super.viewDidDisappear(animated)
        }
        // MARK: - UI Setting
    
        // MARK: - IBAcion
    
        // MARK: - Function
    
    }
    // MARK: - Extensions
    

    取代完後再選取一次按右鍵,選擇Create code Snippet
    可以取名為defaultController,這樣之後就不用一直在複製貼上了

  7. 第七步:驗證我們的 App 第一次呼吸

    我打開我們剛剛建立的 MainViewController.swift,在viewDidLoad函式裡面加入print(”Hello World!”)

    override func viewDidLoad() {
        super.viewDidLoad()
        print("Hello World!")
    }
    

    按下 Cmd + R 執行 App,會看到右下角的控制台出現Hello World!

    image


今天我們了解了App 的內部結構,並親手完成了專案的改造。

明天,我們就要學習如何用程式碼,在我們的App上做一些事情。


上一篇
Day 4 - 開發習慣:聊聊 Coding Guidelines 與如何讓 AI 成為你的學習家教
下一篇
Day 6 - 畫面佈局初探:在 XIB 中設定第一個元件與 Auto Layout 約束
系列文
iOS? AI-Yes!:用 Vide Coding 加速我的 Swift 學習曲線6
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言