UIKit — 是什么、核心概念及架构

作者: IT Sectr 发布日期: 2026-04-30 阅读时间: 10 分钟

UIKit 是用于在 iOS 和 macOS 应用程序中构建图形界面的框架。它包含 UIView、UIViewController、控件和 Auto Layout 系统,能够创建自适应和交互式屏幕。根据 Apple Developer Documentation (2025),UIKit 包含 200 多个用于处理窗口、视图、动画、手势和文本的类 — 这是所有 iPhone 和 iPad 应用程序的基础。

要点

  • UIKit — 是 Apple 用于在 iOS、iPadOS 和 macOS 上构建界面的框架,采用命令式方法管理视图。
  • UIView — 所有可视元素的基础类:按钮、文本字段、图像和容器。
  • UIViewController 管理屏幕的生命周期:从视图加载到内存释放。
  • Auto Layout 通过约束系统描述元素的位置,适应不同的屏幕尺寸。
  • 委托 和数据源 — 表格和集合的关键模式,将数据与其显示分离。

什么是 UIKit?

UIKit — 是 Apple 提供的框架,用于在 iOS、iPadOS 和 macOS(通过 Mac Catalyst)上创建和管理用户界面。它运行在 Core Animation、Core Graphics 和 Quartz Core 之上,将底层渲染抽象为高级对象 — 按钮、标签、图像和容器。UIKit 于 2007 年随 iPhone OS 1 一同出现,至今仍是与 SwiftUI 并行的 iOS 开发主要框架。

该框架遵循命令式方法:开发者创建 UIButton、UILabel、UIImageView 类的实例,设置其属性(颜色、字体、位置),并通过 addSubview 将其添加到视图层次结构中。界面的每次更改都显式执行 — 背后没有任何魔法更新。这使 UIKit 与声明式框架(如 SwiftUI)区分开来,在 SwiftUI 中,状态描述会自动重绘界面。

UIKit 的主要类

该框架包含多个类别的类。UIView — 所有可视组件继承自的基本元素。UIWindow — 用于在屏幕上显示视图的最高级别容器。UIViewController — 管理一组视图并对屏幕旋转、键盘出现和系统通知做出响应的控制器。UIApplication — 处理触摸和按钮按下事件的入口点。

文本使用 UILabel(静态文本)、UITextField(单行输入)、UITextView(多行输入)。按钮 — UIButton,包括系统按钮、自定义按钮和带有 SF Symbols 图标的按钮。导航 — UINavigationController、UITabBarController 和 UISplitViewController。总共 UIKit 包含 200 多个公共类。

UIKit 架构:层与视图层次结构

UIKit 架构 基于层构建:每层负责其自身的显示方面。最底层是 Core Graphics — 路径、文本和图像的渲染引擎。上一层 — Core Animation,管理层的组合(CALayer)和状态之间的动画。UIKit 在其上构建了面向对象的 API:UIView、UIViewController 和 UIResponder。

每个应用程序都有一个视图层次结构(view hierarchy) — 以 UIWindow 为根的树。其下是根 UIViewController、其视图以及内部嵌套的子视图。触摸事件沿着响应者链(responder chain)传播:从最内层的视图到父视图,再到 UIApplication。如果没有对象处理触摸,则忽略该触摸。

UIView 和 CALayer

每个 UIView 包含一个负责在屏幕上渲染像素的 CALayer 层。视图管理触摸和辅助功能,层管理图形:阴影、圆角、边框、变换。这种分离允许将繁重的图形处理转移到单独的线程(渲染服务器),而不会阻塞主线程。Apple 建议如果屏幕上需要超过 200 个视图,则直接使用 CALayer — 这可以降低 CPU 负载。

响应者链详解

响应者链 从最先接收触摸事件的对象开始。如果它不处理该事件(touchesBegan 方法未被重写),则该事件将传递给链中的下一个响应者:next、superview、next responder、UIViewController、UIWindow、UIApplication、App Delegate。这允许在场景级别拦截全局手势和键盘事件,而无需向每个视图添加处理程序。

UIViewController 的生命周期

每个 UIViewController 都经过严格定义的事件序列。生命周期包括以下阶段:初始化、视图加载、屏幕显示、旋转时布局更新、隐藏、离开屏幕和内存释放。开发人员重写相应的方法以在每个阶段执行其代码。

swift
class ProfileViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        loadUserProfile()
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        clearCache()
    }
}

viewDidLoad 中配置界面 — 创建子视图、设置约束、订阅委托。在 viewWillAppear 中执行显示前的操作:从网络加载新数据、更新值。viewDidDisappear — 取消通知订阅和清理临时数据的位置。在所有重写中必须调用 super,否则事件链将被中断。

内存管理和 viewDidUnload

在旧版本的 iOS 中,存在 viewDidUnload 方法,在内存不足时调用。从 iOS 6 开始,该方法已被删除 — 现在 UIKit 会在控制器的视图不可见时自动卸载它们。开发人员只需将所有对视图的引用声明为 weak,以便 ARC 在收到系统警告时正确释放内存。

控制器之间的转场

UIKit 支持两种类型的转场:segue(通过 Storyboard)和通过 UINavigationController 进行编程导航。编程转场如下:navigationController?.pushViewController(detailVC, animated: true)。此时 detailVC 的生命周期正常进行 — viewDidLoad 被调用一次,viewWillAppear — 每次显示时调用。

Auto Layout 与自适应布局

Auto Layout — 是一种基于数学关系(约束)的元素定位系统。开发者无需使用固定的 X 和 Y 坐标,而是描述规则:「按钮位于标签右侧,间距 16pt」或「视图在屏幕宽度上拉伸,左右边距 20pt」。系统在运行时求解生成的方程组,使界面适应任何屏幕尺寸。

约束可以在 Interface Builder(通过拖放)或以编程方式在 Swift 中设置。每个约束都是 NSLayoutConstraint 类的实例,参数包括:firstItem、firstAttribute、relation、secondItem、secondAttribute、multiplier、constant。约束通过 isActive = true 或批量通过 NSLayoutConstraint.activate() 激活。

安全区域和布局边距

随着 iPhone X(2017)的推出,Apple 引入了 Safe Area — 屏幕中没有刘海、圆角和 home 条指示器的区域。约束应绑定到 view.safeAreaLayoutGuide,而不是 viewLayout Margins 添加视图的内部边距,默认根据上下文为 8pt 或 16pt。使用 safeAreaLayoutGuide 可确保在所有 iPhone 和 iPad 上正确显示。

约束动画

Auto Layout 支持通过更改约束的常量来实现动画。只需更新约束的 constant 并在动画块中调用带有 layoutIfNeededUIView.animate。系统会平滑地重新计算层次结构中所有视图的位置。此技术用于可展开块、自适应键盘面板和屏幕方向更改。

使用表格和集合

UITableViewUICollectionView — UIKit 中用于显示列表和网格的两个强大工具。UITableView 适用于单列垂直列表(聊天、设置、新闻源)。UICollectionView — 适用于网格、水平列表、轮播和自定义布局(图库、产品、日历)。两个类都使用委托模式来分离数据和外观。

数据源是 UITableViewDataSource 协议,包含必需的方法 numberOfRowsInSectioncellForRowAt。委托 UITableViewDelegate 处理单元格点击、行高和滚动事件。重用标识符机制会重用已离开屏幕的单元格,这对于大型列表的性能至关重要。

swift
class ContactsViewController: UITableViewController {

    private let contacts = ["安娜", "鲍里斯", "维克多"]

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(UITableViewCell.self,
                           forCellReuseIdentifier: "cell")
    }

    override func tableView(_ tableView: UITableView,
                          numberOfRowsInSection section: Int) -> Int {
        return contacts.count
    }

    override func tableView(_ tableView: UITableView,
                          cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell",
                                                 for: indexPath)
        var content = cell.defaultContentConfiguration()
        content.text = contacts[indexPath.row]
        cell.contentConfiguration = content
        return cell
    }
}

示例显示了一个用于显示字符串数组的最小控制器。单元格通过 UIListContentConfiguration 配置 — 这是一种现代 API(iOS 14+),取代了已弃用的 textLabeldetailTextLabel。在 viewDidLoad 中注册单元格类是强制性的,否则应用程序将在运行时崩溃并抛出异常。

UICollectionView 和组合布局

从 iOS 13 开始,Apple 推荐使用 UICollectionViewCompositionalLayout 来构建复杂布局。开发者以声明方式描述节、组、元素及其大小 — 获得具有任意几何形状的网格:条带、2x2 网格、轮播、装饰。组合布局已在所有新项目中取代了已弃用的 UICollectionViewFlowLayout。结合 DiffableDataSource,集合的更新简化为一次 apply(snapshot) 调用,并且更改的动画会自动执行。

Swift 代码示例

以下是在实际任务中使用 UIKit 的两个实际示例:创建具有阴影和圆角的自定义视图,以及处理滑动手势以从列表中删除元素。

swift
extension UIView {
    func applyCardStyle() {
        layer.cornerRadius = 12
        layer.shadowOpacity = 0.15
        layer.shadowRadius = 8
        layer.shadowOffset = CGSize(width: 0, height: 2)
        layer.masksToBounds = false
    }
}

@objc private func handleSwipe(_ gesture: UISwipeGestureRecognizer) {
    guard let swipedView = gesture.view else { return }
    UIView.animate(withDuration: 0.3) {
        swipedView.alpha = 0
        swipedView.transform = CGAffineTransform(translationX: 300, y: 0)
    } completion: { _ in
        swipedView.removeFromSuperview()
    }
}

applyCardStyle 扩展为任何视图添加阴影和圆角 — 适用于产品卡片、个人资料和通知。带有动画的 handleSwipe 方法在用户向右滑动时删除该元素。处理程序通过 addGestureRecognizer 添加到视图中,配置为 UISwipeGestureRecognizer(direction: .right)。设置 masksToBounds = false 很重要,这样阴影就不会被视图边界裁剪。

对于更复杂的界面,请使用 UIStackView — 一个自动水平或垂直分布嵌套视图的容器。Stack View 简化了布局:无需为每个元素设置约束,只需为堆栈本身设置一个约束即可。

常见问题

UIView 中 frame 和 bounds 有什么区别?

Frame — 在父视图坐标中的矩形(位置 + 大小)。Bounds — 在视图自身坐标中的矩形(始终从 0,0 开始)。Frame 在旋转和缩放时改变,bounds — 不变。

如何释放未使用视图的内存?

UIKit 会自动卸载隐藏控制器的视图。开发者只需将视图属性声明为 weak var,以便 ARC 在收到系统警告时释放内存。

2026 年是否值得使用 Storyboard?

对于新项目,Apple 推荐使用 SwiftUI。如果项目基于 UIKit — 对单个屏幕使用 XIB 或通过 SnapKit 使用编程布局。Storyboard 会产生合并冲突并减慢构建速度。

如何在 UIKit 中实现深色模式?

使用带有 traitCollection 支持的 UIColorUIColor { $0.userInterfaceStyle == .dark ? ... : ... }。在 Info.plist 中使用 UIUserInterfaceStyle 键激活深色模式。

UIStackView 比手动约束好在哪里?

UIStackView 根据对齐方式、分布和间距自动计算嵌套视图的位置和大小。这可将约束代码减少 60–80%,并简化对不同屏幕的适配。

总结

  • UIKit — Apple 用于构建 iOS、iPadOS 和 macOS 界面的主要框架,采用命令式方法。
  • UIView 管理渲染和触摸;其图形部分由在单独线程上运行的 CALayer 层处理。
  • UIViewController 经历严格的生命周期:从 viewDidLoad 到内存释放,可以重写每个阶段。
  • Auto Layout 用约束系统取代了固定坐标,使界面适应任何屏幕和方向。
  • UITableViewUICollectionView 通过重用标识符确保大型列表的性能,并支持现代组合布局。
  • UIStackView 简化了视图序列的布局,将约束代码减少 60–80%。
  • 对于新项目,Apple 推荐 SwiftUI,但 UIKit 在支持旧版 iOS 和复杂自定义界面方面仍然很重要。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读