SwiftUI:它是什么、关键概念及View Protocol

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

SwiftUI是Apple的一个声明式框架,用于在生态系统中的所有平台上构建用户界面。无需命令式地描述步骤,开发者只需声明界面的外观,SwiftUI就会负责其渲染和更新。根据Apple Developer Documentation (2025),SwiftUI支持iOS 15+、iPadOS 15+、macOS 12+、watchOS 8+和tvOS 15+,并使用View Protocol作为所有界面组件的基础构建块。

要点

  • SwiftUI — Apple的声明式框架,开发者描述界面,更新自动执行。
  • View Protocol及其body属性 — 每个SwiftUI UI组件的基础,通过视图组合返回屏幕描述。
  • Property Wrappers — @State、@Binding、@ObservedObject、@StateObject — 管理状态并在数据更改时触发重绘。
  • NavigationStack (iOS 16+) — 具有类型安全路由和声明式转换的现代导航API。
  • Modifier — 用于配置视图外观和行为的链式调用,无需类继承。

什么是SwiftUI?

SwiftUI是一个声明式框架,由Apple于2019年推出,用于在新项目中取代UIKit。开发者无需手动创建UIView实例并将其添加到层次结构中,而是通过实现View协议的结构来描述界面。SwiftUI自动计算当前状态和新状态之间的差异,并使用自己的渲染引擎仅重绘更改的部分。

该框架使用Swift编写,采用值语义(结构体而非类),这使得UI组件轻量且线程安全。与UIKit不同,在UIKit中UIViewController由于Objective-C运行时可能占用200+字节,而SwiftUI View只是一个几字节大小的结构体。这对于内存有限的watchOS尤其重要。

SwiftUI的跨平台性

相同的View描述可以在iPhone、iPad、Mac、Apple Watch、Apple TV和Apple Vision Pro上运行。SwiftUI会根据平台调整界面:在iOS上使用触控手势,在macOS上使用键盘快捷键,在watchOS上使用Digital Crown滚动。这缩短了在多个Apple平台上发布应用的公司的开发时间,但需要针对每个平台的特定元素进行额外配置。

View Protocol和视图主体

SwiftUI中,每个屏幕都是一个实现View协议的结构,只有一个要求:some View类型的计算属性body。关键字some(不透明类型)隐藏了视图的具体类型,使SwiftUI能够优化渲染。在body内部,开发者使用ViewBuilder组合现成的组件——Text、Image、Button、List——将多个视图合并为一个。

swift
struct GreetingView: View {
    let name: String

    var var body: some View {
        VStack {
            Text("你好,\(name)!")
                .font(.title)
                .foregroundColor(.blue)
            Image(systemName: "hand.wave")
                .imageScale(.large)
        }
        .padding()
    }
}

在示例中,VStack(垂直堆栈)包含Text和Image。name值通过结构体的初始化器传递——这就是SwiftUI中无需外部DI容器的依赖注入(DI)的工作方式。每个修饰符返回应用了更改的新视图,而不改变原始视图。这是通过值类型的不可变性实现的。

ViewBuilder和条件语句

ViewBuilder是一个结果构建器,使用@resultBuilder注解,可将最多10个视图合并为一个。在body内部,可以使用if/else、switch和ForEach而无需额外的包装器。ForEach与Identifiable元素一起使用——每个视图获得唯一的id,以便在插入/删除时进行正确的动画。

状态管理:@State、@Binding、@ObservedObject

SwiftUI中,状态决定屏幕上显示的内容。当状态发生变化时,SwiftUI会重新创建依赖视图的body,并将结果与之前的结果进行比较,应用差异算法。使用属性包装器(property wrappers)来存储状态——每个包装器解决自己的任务:本地状态、与子视图的连接或外部数据模型。

swift
struct CounterView: View {
    @State private var count = 0

    var var body: some View {
        VStack {
            Text("计数器:\(count)")
            Button("增加") {
                count += 1
            }
        }
    }
}

class UserViewModel: ObservableObject {
    @Published var name = ""
    @Published var age = 0
}

@State在View结构体内存储局部简单值(Int、String、Bool)。SwiftUI将内存从结构体转移到单独的存储空间——因此即使View是值类型,带有@State的属性也可以被修改(改变)。@ObservableObject用于具有@Published属性的类,其更改会自动通知SwiftUI需要重绘。

@Binding和父子关系

@Binding创建与父视图中数据源的双向连接。父视图传递$variable(投影值),子视图通过绑定读取和写入值。这允许将文本输入或开关提取到单独的组件中,同时将状态保留在父视图中。没有@Binding,每次更改都需要回调闭包来向上传递新值。

在iOS 16之前,SwiftUI中的导航基于NavigationView——一个在iPad上具有复杂行为(拆分视图、双列)的过时API。从iOS 16开始,Apple推荐NavigationStack——一个具有类型安全路由的简化替代方案。开发者定义可能路由的枚举,NavigationStack自动管理屏幕堆栈,支持深层链接和返回根视图。

swift
enum Route: Hashable {
    case detail(id: Int)
    case settings
}

struct ContentView: View {
    var var body: some View {
        NavigationStack {
            List {
                NavigationLink("详情页面",
                               value: Route.detail(id: 42))
                NavigationLink("设置",
                               value: Route.settings)
            }
            .navigationDestination(for: Route.self) { route in
                switch route {
                case .detail(let id): DetailView(id: id)
                case .settings: SettingsView()
                }
            }
        }
    }
}

Route类型的路由:Hashable允许使用任何数据类型传递参数。navigationDestination(for:destination:)将路由类型与目标视图连接。与UIKit导航相比的优势:添加新路由时无需重绘——只需在枚举中添加case并在switch中添加处理程序即可。深层链接通过NavigationStack上的processDeepLink处理。

编程导航

对于编程式转换(登录后、计时器或服务器响应后),使用@State和NavigationLink初始化器:NavigationLink(isActive: $isActive)。设置isActive = true后,无需用户触摸即可进行转换。替代方案:在NavigationStack中绑定$path数组:$path.append(Route.detail(id: 1))

View Modifier — 外观配置

Modifier是一种返回视图修改副本的方法。与UIKit不同,在UIKit中属性的配置是通过修改现有视图完成的,而SwiftUI创建应用了更改的新值。修饰符链(chaining)通过顺序转换构建最终界面:字体→间距→颜色→阴影→手势。

Apple提供了200多个内置修饰符。最常见的有:.font().foregroundColor().padding().background().cornerRadius().shadow().opacity().offset()。修饰符的顺序很重要:.padding().background()之前会为带有间距的区域着色,之后仅着色内部区域。自定义修饰符通过ViewModifier协议创建。

条件修饰符和动画

修饰符可以通过三元运算符有条件地应用:.foregroundColor(isError ? .red : .primary)。动画使用.animation(.easeInOut, value: state)——动画修饰符绑定到状态的特定属性。当此属性更改时,SwiftUI会在旧值和新值之间进行动画过渡。动画支持opacity、offset、scale、rotation、大小和颜色——每个属性都有相应的AnimatableParameter。

对于自定义动画,可使用.transition(出现/消失)和.matchedGeometryEffect(元素在两个容器之间的平滑过渡)。后者用于列表中的英雄动画:列表单元格中的图标平滑地转变为详情屏幕上的大图像。

SwiftUI vs UIKit:方法比较

SwiftUI和UIKit之间选择是iOS开发者的首要难题之一。两个框架都得到Apple的支持,但以根本不同的方式解决构建界面的任务:SwiftUI采用声明式,UIKit采用命令式。差异体现在状态管理、导航、性能和兼容性方面。

方面SwiftUIUIKit
方法声明式:显示什么命令式:如何构建
状态Property Wrappers,自动重绘手动:reloadData、setNeedsLayout
UI代码简洁,修饰符链冗长,NSCoder/Storyboard/约束
性能iOS 17+上高,diff算法iOS 12–16上峰值,直接控制
最低版本iOS 15+(完全支持)iOS 2+(所有版本)

对于最低版本为iOS 17的新项目,Apple推荐SwiftUI作为主要框架。对于需要精细控制渲染的界面(自定义UICollectionViewLayout、复杂的CAAnimation场景)或支持iOS 12–14,UIKit仍然是必需的。许多项目采用混合方法:SwiftUI通过UIHostingController嵌入到UIKit应用中,而UIViewRepresentable允许在SwiftUI层次结构中使用UIKit组件。

常见问题

能否在同一项目中使用SwiftUI和UIKit?

可以,通过UIHostingController(SwiftUI在UIKit中)和UIViewRepresentable(UIKit在SwiftUI中)。这是一种混合方法,在迁移时很流行。

从哪个iOS版本开始SwiftUI项目?

iOS 17 — 完整功能:NavigationStack、Observation framework、Swift Charts。iOS 15 — 生产环境的最低门槛。

为什么SwiftUI有时不更新界面?

最常见的原因是在后台线程上更改@Published属性。ObservableObject必须将更改发送到main actor:@MainActor class ViewModel

如何在SwiftUI中处理带延迟的按钮点击?

通过Combine使用.debounceButton.publisher(for: .tap) .debounce(for: .seconds(0.3), scheduler: RunLoop.main)

SwiftUI支持自定义手势吗?

支持,通过Gesture修饰符:DragGesture、LongPressGesture、MagnificationGesture、RotationGesture。通过.simultaneousGesture()和.sequenced()组合它们。

总结

  • SwiftUI — Apple的声明式框架,界面被描述为View结构的组合,使用属性包装器进行状态管理。
  • View Protocol及计算属性body — 每个视图的唯一入口点。ViewBuilder将最多10个视图合并为一个,无需额外的容器。
  • @State@Binding@ObservedObject涵盖所有数据管理场景:本地状态、父子关系和外部模型。
  • NavigationStack使用类型安全的枚举路由取代了NavigationView,增加了对深层链接和编程式导航的支持。
  • Modifier — SwiftUI的关键模式,允许通过链式调用配置视图外观而无需继承。
  • SwiftUI和UIKit通过UIHostingController和UIViewRepresentable共存,允许项目逐步迁移。
  • 对于iOS 17+,Apple推荐SwiftUI作为主要框架;UIKit保留用于复杂的自定义界面和旧版本支持。

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

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

讨论项目

另请阅读