swiftUI 快速上手入门笔记说明

9 阅读3分钟

既然你已经有了 Swift 基础,学习 SwiftUI 会非常顺畅。SwiftUI 是一种 声明式 的 UI 框架,与你之前可能用过的 UIKit(命令式)在思维方式上有很大不同。

以下是基于你现有基础整理的 SwiftUI 快速上手指南:

2. SwiftUI 核心架构

View 协议

在 SwiftUI 中,所有东西都是 View。你的界面由一个个遵循 View 协议的结构体组成。

import SwiftUI

struct ContentView: View { // 1. 遵循 View 协议的结构体
    var body: some View {   // 2. 必须实现 computed property `body`
        Text("Hello, World!") // 3. 返回一个 View
    }
}

组合优于继承

UIKit 喜欢继承(例如继承 UIViewController),SwiftUI 喜欢组合。你把小的视图拼成大的视图。

struct UserInfoView: View {
    var name: String
    
    var body: some View {
        HStack { // 水平排列
            Image(systemName: "person.circle") // 系统图标
                .font(.largeTitle)
            VStack(alignment: .leading) { // 垂直排列
                Text("用户名:")
                    .font(.caption)
                Text(name)
                    .font(.title)
            }
            Spacer() // 弹性空间,把内容推到左边
        }
        .padding() // 添加内边距
        .background(Color.gray.opacity(0.2)) // 背景色
        .cornerRadius(10) // 圆角
    }
}

3. 基础布局组件

用你熟悉的 Swift 语法来创建 UI:

  • VStack:垂直排列视图。
  • HStack:水平排列视图。
  • ZStack:重叠排列视图(类似于 UIKit 的 addSubview,后添加的在上面)。
  • List:类似 UITableView,用于展示滚动列表。
  • NavigationStack:类似 UINavigationController,用于页面导航。
  • Form:专门用来做设置页或输入页的表单。

4. 状态管理 (@State 和 @Binding)

这是 SwiftUI 的精华。既然你有 Swift 基础,可以把它理解为一种属性包装器,它让值类型(struct)拥有了类似引用的能力来触发 UI 刷新。

  • @State:用于视图内部的私有数据。当值改变时,body 会自动刷新。
  • @Binding:用于传递引用。一个视图持有数据源,另一个视图想读写这个数据但不拥有它。

举个计数器例子:

struct CounterView: View {
    @State private var count = 0 // 数据源
    
    var body: some View {
        VStack {
            Text("Count: \(count)")
                .font(.largeTitle)
            
            // 传递 $count (binding) 给子视图
            CounterButton(count: $count)
        }
    }
}

struct CounterButton: View {
    @Binding var count: Int // 我不拥有数据,我只是引用它
    
    var body: some View {
        Button("Increment") { // 按钮
            count += 1 // 修改时,会通知 CounterView 刷新
        }
        .padding()
        .background(Color.blue)
        .foregroundColor(.white)
        .cornerRadius(10)
    }
}

5. 数据流进阶 (MVVM 模式)

除了 @State 用于局部,还有更强大的数据管理工具来处理复杂业务逻辑:

  • ObservableObject:这是一个协议,通常用于你的 ViewModel 类。
  • @Published:属性包装器,标记 VM 中那些需要触发 UI 刷新的属性。
  • @StateObject / @ObservedObject:在 View 中引用 VM 对象。
    • @StateObject:View 持有该对象的生命周期(负责创建)。
    • @ObservedObject:View 引用从外部传入的对象(不负责创建)。

// 2. View 结构体
struct UserProfileView: View {
    @StateObject private var viewModel = UserViewModel() // 持有 VM
    
    var body: some View {
        VStack {
            Text("Name: \(viewModel.username)")
            Text("Age: \(viewModel.age)")
            
            Button("Change Name") {
                viewModel.updateName()
            }
        }
    }
}

6. 布局与修饰符 (Modifiers)

在 SwiftUI 中,你通过修饰符来设置视图的属性(类似于 UIKit 中的 .property = value),链式调用非常优雅。

常用修饰符:

  • .padding():设置内边距。
  • .foregroundColor():前景色(文字颜色/图标颜色)。
  • .background():背景。
  • .font():字体。
  • .frame():设置宽高。
  • .clipShape():裁剪形状(如圆角)。

7. 项目结构建议

一个典型的 SwiftUI 文件通常长这样:

import SwiftUI

// MARK: - Model (如果简单的话)
struct Item {
    let name: String
}

// MARK: - ViewModel (如果需要的话)
class ItemListViewModel: ObservableObject {
    @Published var items = [Item(name: "Apple"), Item(name: "Banana")]
}

// MARK: - View
struct ItemListView: View {
    @StateObject private var viewModel = ItemListViewModel()
    
    var body: some View {
        NavigationStack {
            List(viewModel.items, id: \.name) { item in // 遍历数据
                ItemRowView(item: item)
            }
            .navigationTitle("Items")
        }
    }
}

struct ItemRowView: View {
    let item: Item
    
    var body: some View {
        HStack {
            Text(item.name)
            Spacer()
            Image(systemName: "info.circle")
        }
        .padding(.vertical, 4)
    }
}

给你的学习建议

  1. 忘掉 Frame 和约束:SwiftUI 更多依赖于 Stack + Spacer + Padding 来实现布局,而不是 NSLayoutConstraint
  2. 善用 Preview:SwiftUI 的 Canvas 预览非常好用。你可以一边写代码,一边实时看到 UI 变化。
  3. 遇到 UIKit 组件找不到时:SwiftUI 虽然强大,但有些 UIKit 的复杂组件暂时没有(比如 UICollectionView 的高级布局)。这时候你需要用 UIViewRepresentable 来包装 UIKit 组件,这是另一个进阶话题。

有什么具体的 UI 或逻辑想用 SwiftUI 实现吗?