SwiftUI 5 新能力梳理:动画、数据绑定与导航
SwiftUI 5 的变化很多,真正影响日常开发的主要是动画、数据流和导航。下面结合示例,看看它们在项目中的实际用法。
新的动画系统
SwiftUI 5.0 引入了全新的动画系统,提供了更加灵活和强大的动画控制能力。
关键帧动画
新的关键帧动画 API 可以创建复杂的多阶段动画:
struct KeyframeAnimationView: View {
@State private var isAnimating = false
var body: some View {
Circle()
.fill(.blue)
.frame(width: 100, height: 100)
.keyframeAnimator(
initialValue: AnimationValues(),
repeating: isAnimating
) { content, value in
content
.scaleEffect(value.scale)
.rotationEffect(value.rotation)
.offset(value.offset)
} keyframes: { _ in
KeyframeTrack(.scale) {
SpringKeyframe(1.2, duration: 0.5)
SpringKeyframe(1.0, duration: 0.5)
}
KeyframeTrack(.rotation) {
LinearKeyframe(.degrees(0), duration: 0.0)
LinearKeyframe(.degrees(360), duration: 1.0)
}
KeyframeTrack(.offset) {
SpringKeyframe(CGSize(width: 100, height: 0), duration: 0.5)
SpringKeyframe(CGSize(width: 0, height: 0), duration: 0.5)
}
}
}
}
struct AnimationValues {
var scale = 1.0
var rotation = Angle.zero
var offset = CGSize.zero
}
阶段动画
阶段动画可以根据不同状态创建相应的动画效果:
enum LoadingPhase: CaseIterable {
case initial, loading, success, error
}
struct PhaseAnimationView: View {
@State private var phase: LoadingPhase = .initial
var body: some View {
RoundedRectangle(cornerRadius: 12)
.fill(colorForPhase(phase))
.frame(width: 200, height: 60)
.phaseAnimator(LoadingPhase.allCases) { content, phase in
content
.scaleEffect(scaleForPhase(phase))
.opacity(opacityForPhase(phase))
} animation: { phase in
switch phase {
case .initial: .easeInOut(duration: 0.3)
case .loading: .easeInOut(duration: 0.8).repeatForever()
case .success: .spring(duration: 0.5)
case .error: .easeInOut(duration: 0.3)
}
}
}
}
改进的数据绑定
SwiftUI 5.0 对数据绑定系统进行了重大改进,引入了新的 @Observable 宏和更强大的数据流管理。
@Observable 宏
新的 @Observable 宏让可观察对象更容易创建:
@Observable
class UserStore {
var name: String = ""
var email: String = ""
var isLoggedIn: Bool = false
func login() {
// 登录逻辑
isLoggedIn = true
}
func logout() {
// 登出逻辑
isLoggedIn = false
name = ""
email = ""
}
}
struct UserProfileView: View {
@State private var userStore = UserStore()
var body: some View {
VStack {
if userStore.isLoggedIn {
Text("欢迎, \(userStore.name)")
Button("登出") {
userStore.logout()
}
} else {
TextField("用户名", text: $userStore.name)
TextField("邮箱", text: $userStore.email)
Button("登录") {
userStore.login()
}
}
}
}
}
增强的导航功能
SwiftUI 5.0 带来了全新的导航系统,提供了更加灵活和强大的导航控制。
NavigationStack 的改进
新的 NavigationStack 提供了更好的导航控制:
struct NavigationExample: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
List {
NavigationLink("用户列表", value: "users")
NavigationLink("设置", value: "settings")
NavigationLink("关于", value: "about")
}
.navigationDestination(for: String.self) { value in
switch value {
case "users":
UserListView()
case "settings":
SettingsView()
case "about":
AboutView()
default:
Text("未知页面")
}
}
}
}
}
性能优化
SwiftUI 5.0 在性能方面也有显著提升,特别是在大型列表和复杂视图的渲染方面。
懒加载改进
新的懒加载机制提供了更好的内存管理:
struct OptimizedListView: View {
let items: [Item]
var body: some View {
LazyVStack(spacing: 8) {
ForEach(items) { item in
ItemRowView(item: item)
.id(item.id)
}
}
.scrollTargetLayout()
}
}
总结
SwiftUI 5 更值得关注的,不是“新”本身,而是它把几件原本麻烦的事做得更顺了:动画控制更细、状态管理更直接、导航行为也更清楚。
如果你正准备把现有项目迁到 SwiftUI 5,可以先从这几组 API 做小范围试点,再回头处理状态管理、导航结构和性能瓶颈。
后面我会继续写迁移过程里的取舍,以及哪些地方最容易出兼容问题。