1。 為什麼2026年是UIKit

Apple在每年的WWDC上強調了SwiftUI的進化,宣言性UI的便利性已經毋庸置疑了。

但是,這個軟體有不能讓步的要求。 那就是將Time-to-Text(從啟動到可以輸入文字的時間)降到500ms以下。

在SwiftUI中,@StateObject的初始化、body的重新評估、.onAppear的定時控制等,存在宣告性UI框架固有的開銷。 這些在一般的應用程式中是可以忽略的程度,但在追求以毫秒為單位的最佳化的場景中是不能忽視的。

另一方面,從UIKit的viewDidAppear呼叫becomeFirstResponder()的路徑是決定論上高速。 ViewController的生命週期很明確,可以準確地控制鍵盤何時顯示。

設計判斷:為了滿足Time-to-Text 500ms以下的非功能要求,採用UIKit。

2。 完全排除Storyboard的理由

僅僅選擇UIKit是不夠的。 Storyboard也有影響啟動效能的開銷。

  • XML解析成本:Storyboard內部是XML檔案,啟動時需要解析
  • Segue解決成本:為了畫面轉換的Segue設定解決需要時間
  • 不必要的複雜性:簡單的備忘錄應用程式Storyboard的視覺設計工具過度

代替,採用了用SceneDelegate直接生成ViewController的方式。

func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
           options connectionOptions: UIScene.ConnectionOptions) {
    PerformanceLogger.shared.signpostBegin(name: "SceneConnect")
    guard let windowScene = (scene as? UIWindowScene) else { return }
    let window = UIWindow(windowScene: windowScene)
    let composeVC = ComposeViewController()
    let navController = UINavigationController(rootViewController: composeVC)
    window.rootViewController = navController
    window.makeKeyAndVisible()
    PerformanceLogger.shared.signpostEnd(name: "SceneConnect")
}

透過這種方法,實現了Storyboard的零解析時間、Segue解決時間零。 透過從SceneDelegate直接生成ComposeViewController,從啟動路徑中完全排除了不必要的處理。

3. viewDidAppear的1行全部完成

UIKit的最大優勢是明確定義了ViewController的生命週期。 viewDidAppear(_:)被呼叫時,檢視完全顯示在螢幕上。 透過在這個確定的時機呼叫becomeFirstResponder(),可以最大限度地減少鍵盤顯示的延遲。

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    activateTextInput()
}

private func activateTextInput() {
    textView.becomeFirstResponder()
    PerformanceLogger.shared.endTimeToText()
}

透過os_signpost以納秒精度進行測量。 PerformanceLogger.shared.endTimeToText()記錄了Signpost的結束事件,使Instruments的詳細分析成為可能。

測量結果:目標是500ms以下。 在透過螢幕錄影測量點選圖示的樣子的記錄(2026年8月11日、iPhone 16e・warm啟動)中,輸入欄的焦點是0.17秒,鍵盤顯示完成是0.4秒。

4。 效能測量的機制

不是“快”的感覺判斷,而是根據定量資料進行設計判斷。

  • PerformanceLogger:包裝os_signpost的定製記錄器。 測量啟動、傳送、UI更新的各個階段
  • Instruments合作:透過Xcode的os_signpost Instrument可以進行奈米秒精度的追蹤
  • 主要指標:Time-to-Text(啟動→可輸入)、Send-to-Reset(傳送按鈕→UI初始化)
  • 持續監控:在開發中的所有構建中進行效能測量,即時檢測迴歸

效能是功能。 即使使用者不明確要求“速度”,慢的應用程式也會不自覺地使用。 正因如此,持續用數值管理效能很重要。

5。 有使用SwiftUI的場景嗎

UIKit並不是一選。 在應用內,也有適合SwiftUI的場景。

  • 設定畫面:在不影響啟動速度的非關鍵畫面中,SwiftUI的宣告性UI可以提高生產力
  • 關鍵路徑的定義:啟動→輸入備忘錄→傳送的核心流程由UIKit維持
  • 混合的複雜性:UIKit和SwiftUI混合時,需要注意UIHostingController的管理和資料流的一致性
  • 現在的判斷:備忘錄應用程式的UI很簡單,用全屏UIKit統一的話可以保持程式碼基礎的一致性

如果未來SwiftUI的效能進一步改善的話,還有重新評價的餘地,但關鍵路徑的UIKit是暫時維持的方針。

常見問題

問。 SwiftUI不能啟動500ms以下嗎?
不是不可能。 但是,在SwiftUI中@StateObject的初始化和body的重新評價部分會增加處理。 在以最快為目標的這個開發中,選擇了可以精細控制生命週期的UIKit(兩者不是在同一條件下測量比較的結果)。
問。 不使用Storyboard的缺點是什麼?
UI的視覺化成為程式碼庫。 無法在Interface Builder中進行拖放設計。 但是備忘錄應用程式的UI很簡單,所以以程式碼為基礎的UI構建不會成為問題。
問題。 實機的測量結果是什麼?
目標是500ms以下。 記錄下來的測量是透過螢幕錄影測量圖示點選的樣子(2026年8月11日,iPhone 16e・warm啟動),輸入欄的焦點是0.17秒,鍵盤顯示完成是0.4秒。 開發中os_signpost記錄區間,用Instruments進行分析。
問。 今後打算過渡到SwiftUI嗎?
臨界路徑(啟動→輸入→傳送)維持UIKit。 關於設定畫面等非關鍵畫面,有考慮採用SwiftUI的餘地。