iOS 开发

SwiftUI 5 新能力梳理:动画、数据绑定与导航

这篇文章按动画、@Observable、NavigationStack 和列表性能几个部分,梳理 SwiftUI 5 在项目里最值得先上手的变化。

李明
2024/12/20
12 分钟阅读
SwiftUIiOSAnimationNavigation

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 做小范围试点,再回头处理状态管理、导航结构和性能瓶颈。


后面我会继续写迁移过程里的取舍,以及哪些地方最容易出兼容问题。

想聊聊技术?

对某篇内容有想法,或想交流做产品的经验,随时来找我。