SwiftUI 教程

SwiftUI - 主页 SwiftUI - 概览 SwiftUI 与 UIkit

SwiftUI 环境

SwiftUI - 环境设置 SwiftUI - 基本组件 SwiftUI - 构建第一个应用程序

SwiftUI 视图

SwiftUI - 视图 SwiftUI - 自定义文本视图 SwiftUI - 自定义图像视图 SwiftUI - 堆栈

SwiftUI 绘制形状

SwiftUI - 形状 SwiftUI - 绘制线条 SwiftUI - 绘制矩形 SwiftUI - 绘制圆角矩形 SwiftUI - 绘制三角形 SwiftUI - 绘制圆形 SwiftUI - 绘制星形 SwiftUI - 绘制多边形 SwiftUI - 绘制饼图 SwiftUI - 使用内置形状

SwiftUI - 文本

SwiftUI - 文本视图 SwiftUI - 文本输入和输出

SwiftUI - 颜色

SwiftUI - 颜色 SwiftUI - 颜色选择器 SwiftUI - 渐变 SwiftUI - 调整颜色

SwiftUI - 效果

SwiftUI - 效果 SwiftUI - 混合效果 SwiftUI - BLur 效果 SwiftUI - 阴影效果 SwiftUI - 悬停效果

SwiftUI - 动画

SwiftUI - 动画 SwiftUI - 创建动画 SwiftUI - 创建显式动画 SwiftUI - 多个动画 SwiftUI - 过渡 SwiftUI - 不对称过渡 SwiftUI - 自定义过渡

SwiftUI - 图像

SwiftUI - 图像 SwiftUI - 图像作为背景 SwiftUI - 旋转图像 SwiftUI - 媒体

SwiftUI - 视图布局

SwiftUI - 视图布局 SwiftUI - 视图大小 SwiftUI - 视图间距 SwiftUI - 视图填充

SwiftUI - UI 控件

SwiftUI - UI 控件 SwiftUI - 按钮 SwiftUI - 复选框 SwiftUI - 菜单栏 SwiftUI - 工具栏 SwiftUI - 搜索栏 SwiftUI - 文本字段 SwiftUI - 滑块 SwiftUI - 切换 SwiftUI - 选择器 SwiftUI - 菜单

SwiftUI - 列表 &表格

SwiftUI - 列表 SwiftUI - 静态列表 SwiftUI - 动态列表 SwiftUI - 自定义列表 SwiftUI - 表格

SwiftUI - 表单

SwiftUI - 表单 SwiftUI - 在部分中拆分表单

SwiftUI - 事件处理

SwiftUI - 事件处理 SwiftUI - 手势 SwiftUI - 剪贴板 SwiftUI - 拖放 SwiftUI - 焦点 SwiftUI - 警报

SwiftUI - 杂项

SwiftUI - 容器 SwiftUI - 导航 SwiftUI - 通知 SwiftUI - 跨平台 UI SwiftUI - 数据 SwiftUI - 可访问性

SwiftUI - 框架集成

SwiftUI - 框架集成 SwiftUI - 与 UIKit 交互 SwiftUI - 创建 macOS 应用

SwiftUI 有用资源

SwiftUI - 有用资源 SwiftUI - 讨论


SwiftUI - 数据

在为 Apple 平台开发响应式和交互式应用程序时,数据管理是一个非常重要且关键的部分。众所周知,SwiftUI 使用声明式方式,应用程序的 UI 将根据底层数据自动更新,因此无论何时数据由于某些外部事件或用户操作而发生变化,它都会直接影响界面的各个部分。

因此,数据及其流和状态的管理非常重要。该框架提供了各种工具,例如状态变量和绑定,以将数据连接到应用程序的 UI。这些工具管理数据的来源或数据中发生的任何变化。以下是 SwiftUI 中最常用的数据管理技术 −

  • @State 属性包装器

  • @Binding 属性包装器

  • @ObservedObject 属性包装器

  • @EnvironmentObject 属性包装器

SwiftUI 中的 @State 属性包装器

@State 属性包装器用于读取和写入由 SwiftUI 管理的值。它为我们存储在视图中的给定值类型保存单一来源。它可以通过使用 @State 属性为所有类型的视图创建状态变量,并且每个状态变量都用某个初始值初始化。

因此,当状态变量的值发生变化时,SwiftUI 将自动更新视图中依赖于状态变量值的那些部分。状态变量通常被声明为私有的,这可以防止它们在范围之外使用。

我们可以改变状态属性。如果我们将状态属性传递给子视图,SwiftUI 将在主容器视图中的值发生变化时更新子视图,而子视图不能修改该值。要修改该值,我们需要将其作为绑定传递。我们也可以在 State 中存储 Observable()。

语法

以下是语法 −

@State private var value : Double = 2.3

示例

以下 SwiftUI 程序创建并访问状态变量。在这里,状态管理计数变量的值,每当计数的值发生变化时,视图都会相应更新。

import SwiftUI
struct ContentView: View {
   // State variable
   @State private var count = 0
   var body: some View {
      VStack {
         Text("Counter: \(count)").font(.largeTitle)
         Button("Increment") {
            count += 1
         }
         .frame(width: 100, height: 60)
         .background(.blue)
         .foregroundStyle(.white)
         .font(.headline)         
      }
   }
}
#Preview {
   ContentView()
}

输出

Data

SwiftUI 中的 @Binding 属性包装器

绑定属性包装器在子视图和父视图之间创建双向关系,以便子视图可以轻松读取和写入父视图数据,反之亦然。

在这里,我们可以根据需要随时更新绑定变量,而无需直接将数据存储在其中。要传递绑定属性包装器,我们需要在属性前使用 $。或者我们可以说,我们可以借助绑定属性包装器将状态属性传递给另一个视图。我们还可以使用 @Binding 属性包装器创建绑定属性。

语法

以下是语法−

@Binding var value : Bool

示例

以下 SwiftUI 程序创建绑定属性。在这里,我们将状态变量作为绑定传递并创建了一个绑定变量。

import SwiftUI
struct ContentView: View {   
   // state variable
   @State private var count = 0
   var body: some View {
      VStack {
         Text("Counter: \(count)").font(.largeTitle).border(.black, width: 4)
         
         // Passing count as a binding
         newView(count: $count)
      }
   }
}
struct newView: View {   
   // Binding variable
   @Binding var count: Int
   var body: some View {
      Button("Increase Value") {
         count += 1
      }
      .frame(width: 130, height: 50)
      .background(.brown)
      .foregroundStyle(.white)
      .font(.headline)
   }
}
#Preview {
   ContentView()
}

输出

Data

SwiftUI 中的 @StateObject 和 @ObservedObject 属性包装器

@ObservedObject 属性包装器用于包装可观察对象并观察它们,而 @StateObject 用于创建和管理可观察对象。这两个包装器都需要符合 ObservableObject 协议的对象。

因此,每当可观察对象的值发生修改时,SwiftUI 都会更新与该对象相关的所有视图。它不包含任何默认值或初始值,可以由子视图使用。这里允许子视图更新属性。

语法

以下是语法−

@StateObject private var model = ObservableObject()
@ObservedObject private var model = ObservableObject()

示例

以下 SwiftUI 程序使用 @StateObject 和 @ObservedObject 属性来管理可观察对象。

import SwiftUI
// 创建可观察对象
class Counter: ObservableObject {
   @Published var count = 0
}
struct ContentView: View {
   @StateObject private var counter = Counter()
   var body: some View {
      
      // 将计数器传递给 newView
      newView(myCounter: counter)
   }
}
struct newView: View {   
   // Observing the model
   @ObservedObject var myCounter: Counter
   var body: some View {
      VStack {
         Text("Count: \(myCounter.count)")
            .font(.largeTitle)
            .bold()
            .padding()
         Button("Increment") {
            myCounter.count += 1
         }
         .frame(width: 130, height: 50)
         .background(.brown)
         .foregroundStyle(.white)
         .font(.headline)
      }
   }
}
#Preview {
   ContentView()
}

输出

Data

SwiftUI 中的 @EnvironmentObject 属性包装器

@EnvironmentObject 属性包装器用于在具有可观察对象的所有视图之间共享数据。它共享数据而无需在视图层次结构中明确传递数据。数据在层次结构中的所有视图的公共环境中共享,如果任何视图更新数据,则它将自动更新所有视图。

共享对象必须符合 ObservableObject 协议,并且其属性必须使用 @Published 定义。共享数据必须在视图层次结构的较高级别的 .environmentObject() 中注入,并且可以使用 @EnvironmentObject 由任何视图访问。

语法

以下是语法 −

@EnvironmentObject var mySettings: ObservableObject()

示例

以下 SwiftUI 程序使用 @EnvironmentObject 设置 dark 模式。

import SwiftUI
class Settings: ObservableObject {
   @Published var darkMode: Bool = false
}
struct ContentView: View {
   @StateObject private var newSettings = Settings()
   var body: some View {
      VStack {
         Text("Original View")
            .font(.largeTitle)
            .padding()
         
         // Toggle dark mode
         ToggleView()
         
         // Display dark mode
         DisplayView()
      }
      
      // 在环境对象中传递 newSettings
      .environmentObject(newSettings)
   }
}
struct ToggleView: View {   
   // Accessing the Settings
   @EnvironmentObject var mySettings: Settings
   var body: some View {      
      // Binding darkMode to the toggle
      Toggle("Dark Mode", isOn: $mySettings.darkMode)
         .padding()
         .frame(width: 200, height: 200)
         .background(mySettings.darkMode ? .black : .white)
         .foregroundStyle(mySettings.darkMode ? .white : .black)
   }
}
struct DisplayView: View {
   
   // Access the Settings
   @EnvironmentObject var settings: Settings

   var body: some View {
      Text("Dark Mode is \(settings.darkMode ? "Activated" : "Deactivated")")
         .font(.title)
         .padding()
         .foregroundStyle(settings.darkMode ? .white : .black)
         .background(settings.darkMode ? .black : .white)
   }
}
#Preview {
   ContentView()
}

输出

数据