当前位置: 首页 > article >正文

SwiftUI之状态管理全解析

文章目录

    • 引言
    • 一、`@State`
      • 1.1 基本概念
      • 1.2 初始化与默认值
      • 1.3 注意事项
    • 二、`@Binding`
      • 2.1 基本概念
      • 2.2 初始化与使用
      • 2.3 注意事项
    • 三、`@ObservedObject`
      • 3.1 基本概念
      • 3.2 初始化与使用
      • 3.3 注意事项
    • 四、`@EnvironmentObject`
      • 4.1 基本概念
      • 4.2 初始化与使用
      • 4.3 注意事项
    • 五、`@StateObject`
      • 5.1 基本概念
      • 5.2 初始化与使用
      • 5.3 注意事项
    • 六、@ObservedObject、@StateObject、@EnvironmentObject区别及使用场景
      • 6.1 区别
        • 6.1.1 对象创建和所有权
        • 6.1.2 生命周期管理
        • 6.1.3 数据传递方式
      • 6.2 使用场景
        • 6.2.1 `@ObservedObject`
        • 6.2.2 `@StateObject`
        • 6.2.3 `@EnvironmentObject`
    • 七、综合案例
      • 7.1 电商购物案例
      • 7.2 代码解释
        • 7.2.1 数据模型
        • 7.2.2 购物车视图模型(`ShoppingCartViewModel`)
        • 7.2.3 商品单元格视图(`ProductCell`)
        • 7.2.4 商品列表视图(`ProductListView`)
        • 7.2.5 购物车视图(`CartView`)
        • 7.2.6 主视图(`MainView`)
    • 八、小结

引言

在 SwiftUI 中,状态管理是构建交互式和动态用户界面的核心。状态代表着应用程序的数据,当这些数据发生变化时,SwiftUI 会自动更新与之关联的视图,以反映最新的状态。本文将详细介绍 SwiftUI 中几种常见的状态管理方式,包括 @State@Binding@ObservedObject@EnvironmentObject@StateObject,并探讨它们的使用场景、初始化、默认值设置以及注意事项。

一、@State

1.1 基本概念

@State 是 SwiftUI 中用于管理视图私有状态的属性包装器。它通常用于存储简单的值,如布尔值、整数、字符串等,并且只能在结构体视图中使用。当 @State 变量的值发生变化时,SwiftUI 会重新计算并更新依赖于该变量的视图部分。

1.2 初始化与默认值

@State 变量必须在声明时进行初始化,因为它代表着视图的初始状态。可以为其提供一个默认值,这个默认值将作为视图首次显示时的状态。

import SwiftUI

struct StateExampleView: View {
   
    // 初始化 @State 变量并设置默认值
    @State private var isFavorite = false

    var body: some View {
   
        Button(action: {
   
            self.isFavorite.toggle()
        }) {
   
            Text(isFavorite ? "已收藏" : "收藏")
        }
    }
}

在上述代码中,isFavorite 是一个 @State 变量,初始值为 false。当按钮被点击时,isFavorite 的值会取反,视图会相应地更新显示内容。
在这里插入图片描述

1.3 注意事项

  • 私有性@State 变量应该是私有的,因为它是视图的内部状态,不应该被外部视图直接访问或修改。
  • 值类型@State 通常用于存储值类型(如结构体、枚举),因为值类型的赋值会创建一个新的副本,这有助于 SwiftUI 检测状态的变化。
  • 视图重建:当 @State 变量的值发生变化时,SwiftUI 会重新计算整个视图的 body 属性,因此应避免在 body 中执行昂贵的操作。

二、@Binding

2.1 基本概念

@Binding 用于在不同视图之间共享状态,实现双向数据绑定。它允许一个视图修改另一个视图的状态,通常用于将父视图的 @State 变量传递给子视图。

2.2 初始化与使用

@Binding 变量不能直接初始化,它必须通过外部传递的 Binding 实例进行赋值。通常在父视图中使用 $ 符号将 @State 变量转换为 Binding 实例,并传递给子视图。

import SwiftUI

// 子视图
struct TextFieldView: View {
   
    @Binding var text: String

    var body: some View {
   
        TextField("输入文本", text: $text)
    }
}

// 父视图
struct BindingExampleView: View {
   
    @State private var inputText = ""

    var body: some View {
   
        VStack {
   
            // 将 @State 变量转换为 Binding 并传递给子视图
            TextFieldView(text: $inputText)
            Text("你输入的文本是: \(inputText)")
        }
    }
}

在上述代码中,TextFieldView 接收一个 @Binding 变量 text,并将其绑定到 TextField 上。父视图 BindingExampleView 将自己的 @State 变量 inputText 通过 $ 符号转换为 Binding 实例传递给子视图。当用户在 TextField 中输入文本时,父视图中的 inputText 会相应更新。
在这里插入图片描述

2.3 注意事项

  • 依赖外部状态@Binding 变量依赖于外部传递的 Binding 实例,因此必须确保在使用之前已经正确初始化。
  • 数据一致性:由于 @Binding 实现了双向数据绑定,任何对 @Binding 变量的修改都会反映到原始的 @State 变量上,需要注意数据的一致性和正确性。

三、@ObservedObject

3.1 基本概念

@ObservedObject 用于观察符合 ObservableObject 协议的对象。当被观察对象的 @Published 属性发生变化时,SwiftUI 会自动更新关联的视图。@ObservedObject 通常用于管理复杂的状态逻辑,将状态和业务逻辑封装在一个独立的对象中。

3.2 初始化与使用

@ObservedObject 变量可以在视图中直接初始化,也可以通过外部传递。被观察的对象必须符合 ObservableObject 协议,并且需要使用 @Published 标记需要观察的属性。

import SwiftUI
import Combine

// 定义一个符合 ObservableObject 协议的类
class CounterViewModel: ObservableObject {
   
    // 使用 @Published 标记需要观察的属性
    @Published var count = 0

    func increment() {
   
        count += 1
    }
}

struct ObservedObjectExampleView: View {
   
    // 初始化 @ObservedObject 变量
    @ObservedObject private var viewModel = CounterViewModel()

    var body: some View {
   
        VStack {
   
            Text("计数: \(viewModel.count)")
            Button(action: {
   
                self.viewModel.increment()
            }) {
   
                Text("增加计数")
            }
        }
    }
}

在上述代码中,CounterViewModel 是一个符合 ObservableObject 协议的类,包含一个 @Published 属性 countObservedObjectExampleView 使用 @ObservedObject 观察 CounterViewModel 的实例。当点击按钮调用 viewModel.increment() 方法时,count 属性的值会改变,SwiftUI 会自动更新 Text 视图以显示新的计数。
在这里插入图片描述

3.3 注意事项

  • 对象生命周期@ObservedObject 不会管理被观察对象的生命周期,因此需要确保对象在视图使用期间不会被销毁。通常在父视图中创建对象并传递给子视图,或者使用 @StateObject 来管理对象的生命周期。
  • 线程安全@Published 属性的修改应该在主线程上进行,因为 SwiftUI 的视图更新是在主线程上执行的。如果在后台线程中修改 @Published 属性,可能会导致视图更新不一致或崩溃。

四、@EnvironmentObject

4.1 基本概念

@EnvironmentObject 用于在整个视图层次结构中共享一个 ObservableObject 实例。与 @ObservedObject 不同的是,@EnvironmentObject 可以在多个视图中轻松访问同一个状态对象,而不需要通过层层传递参数。

4.2 初始化与使用

@EnvironmentObject 变量不需要在视图中初始化,它会从视图环境中获取共享的 ObservableObject 实例。在父视图中,需要使用 environmentObject 修饰符将 ObservableObject 实例注入到视图环境中。

import SwiftUI
import Combine


http://www.kler.cn/a/568865.html

相关文章:

  • 大语言模型学习--LangChain
  • webpack5在生产环境屏蔽掉控制台打印 失效处理
  • 阿里云服务器宝塔终端如何创建fastadmin插件
  • 神经网络之RNN和LSTM(基于pytorch-api)
  • 基于图神经网络的会话推荐经典论文
  • 一键安装Mysql部署脚本之Linux在线安装Mysql,脚本化自动化执行服务器部署(附执行脚本下载)
  • 在.net中,async/await的理解
  • 微服务组件详解——sentinel
  • centos7使用rpm包安装mysql5.6和mysql8.0
  • Scala的match表达式的基本简单介绍
  • Redis的持久化-RDBAOF
  • JeeWMS graphReportController.do SQL注入漏洞复现(CVE-2025-0392)
  • Android嵌套滑动造成的滑动冲突原理分析
  • 补题蓝桥杯14届JavaB组第4题
  • 搭建elasticsearch集群,8.17.0版本
  • SpringCloud基础学习
  • 单片机知多少-STM32-GPIO-寄存器
  • 蓝桥杯刷题(Cows in a Skyscraper G,炮兵阵营)
  • java23种设计模式-迭代器模式
  • 数据挖掘实习面经一