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的余地。