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

【iOS】SwiftUI状态管理

@State @ObservedObject @StateObject 的使用

import SwiftUI

class CountModel: ObservableObject {
    @Published var count: Int = 0 // 通过 @Published 标记的变量会触发视图更新

    init() {
        print("TimerModel initialized at \(count)")
    }
}

struct ContentView: View {
    @State private var count: Int = 0 // 声明一个状态变量

    @ObservedObject private var model = CountModel() // 观察一个可观察对象

    @StateObject private var model2 = CountModel()

    var body: some View {
        VStack {
            Text("Parent Count: \(count)")

            Button {
                count += 1 // 修改可观察对象中的变量
            } label: {
                Text("parent count")
            }

            Text("parent model Count \(model.count)")
            Button {
                model.count += 1 // 修改可观察对象中的变量
                model2.count += 1 // 修改可观察对象中的变量

            } label: {
                Text("model count")
            }

            ChildView(count: $count, model: model, model2: model2) // 通过绑定将状态传递给子视图
        }
    }
}

struct ChildView: View {
    @Binding var count: Int // 子视图中的绑定变量

    @ObservedObject var model: CountModel
    @ObservedObject var model2: CountModel

    var body: some View {
        Button(action: {
            count += 1 // 修改绑定的状态
        }) {
            Text("Child \(count) modelcount: \(model.count) model2 count \(model2.count)")
        }
    }
}

#Preview {
    ContentView()
}

在这里插入图片描述
使用@ObservedObject的对象直接传递给子类的效果和@StateObject虽然可以达到同样的效果,但是不安全。
在这里插入图片描述

@EnvironmentObject @Environment @AppStorage

@EnvironmentObject 需要将数据从父类传递给子类;
@AppStorage 全局可用,使用UserDefaults也可以修改数据;


// 可观察对象,用来存储应用的状态
class UserSettings: ObservableObject {
    @Published var username: String = "Guest"
}

struct ContentView2: View {
    @EnvironmentObject var userSettings: UserSettings // 从环境中获取共享的数据

    @Environment(\.appTheme) var appTheme
    
    @AppStorage("isDarkMode") var isDarkMode: Bool = false

    var body: some View {
        VStack {
            Text("Hello, \(userSettings.username) isDarkMode: \(isDarkMode)")
                .background(appTheme.backgroundColor) // 使用环境中传递的主题背景色
                .foregroundColor(appTheme.textColor) // 使用环境中传递的主题文字色
            Button("Change Username in Content") {
                userSettings.username = "Content" // 修改用户名,视图会自动更新
                isDarkMode.toggle()
            }
        }
        .padding()
    }
}

struct AnotherView: View {
    @EnvironmentObject var userSettings: UserSettings
    
    // @AppStorage
    // @AppStorage 是一种属性包装器,用于将数据存储到应用的 UserDefaults 中,并且能够使得数据在视图间保持同步。
    // 它允许你轻松地从 UserDefaults 获取和存储数据,同时自动处理视图的更新。。
    // 它非常适合在应用程序中持久化小型设置或状态,如主题、语言选择等。当 UserDefaults 中的数据发生变化时,视图会自动重新渲染。
    @AppStorage("isDarkMode") var isDarkMode: Bool = false

    var body: some View {
        VStack {
            Text("AnotherView Hello: \(userSettings.username) isDarkMode: \(isDarkMode)")
            Button("Change Username in Another View") {
                userSettings.username = "Another"
                UserDefaults().set(true, forKey: "isDarkMode")
            }

            ThreeLevelView()
        }
    }
}

struct ThreeLevelView: View {
    @EnvironmentObject var userSettings: UserSettings

    var body: some View {
        VStack {
            Text("ThreeLevelView Hello: \(userSettings.username)")
            Button("Change Username in ThreeLevelView") {
                userSettings.username = "Three Level"
            }
        }
    }
}

struct ParentView: View {
    @EnvironmentObject var userSettings: UserSettings

    var body: some View {
        VStack {
            ContentView2()
            AnotherView()
        }
    }
}

struct HomePageView: View {
    @StateObject private var userSettings = UserSettings()

    let lightTheme = AppTheme(backgroundColor: .white, textColor: .black)
    let darkTheme = AppTheme(backgroundColor: .red, textColor: .white)

    @Environment(\.colorScheme) var colorScheme1 // 获取当前的颜色模式
    @Environment(\.horizontalSizeClass) var sizeClass // 获取当前设备的横向布局类

    var body: some View {
        VStack {
            Text("HomePage Hello: \(userSettings.username)")
            Button("Change Username in HomePage") {
                userSettings.username = "HomePage"
            }
        }
        // @Environment
        // @Environment属性包装器用于从视图的环境中获取系统提供的或由父视图注入的共享数据,而不需要显示地通过属性传递数据。
        // 它能让你访问与当前环境相关的信息,并在视图中进行响应式更新。
        // 基本语法: @Environment(\.key) var value@Environment(\.key) var value
        // key:系统环境值的键或自定义的环境键,用来标识要获取的环境数据.
        //  value:存储在环境中的实际值,可以是任何类型.
        // SwiftUI 提供了一些常用的系统级别的环境数据,比如: 当前的颜色模式,设备的横向布局类
        ParentView().environmentObject(userSettings).environment(\.appTheme, darkTheme)
    }
}

struct AppTheme {
    var backgroundColor: Color
    var textColor: Color
}

struct AppThemeKey: EnvironmentKey {
    // 为这个环境键提供默认值
    static let defaultValue: AppTheme = .init(backgroundColor: .red, textColor: .yellow)
}

extension EnvironmentValues {
    var appTheme: AppTheme {
        get { self[AppThemeKey.self] }
        set { self[AppThemeKey.self] = newValue }
    }
}

#Preview {
    HomePageView()
}

其它链接:
SwiftUI 中的状态管理

相关文章:

  • Python elasticsearch客户端连接常见问题整理
  • 内容中台:解锁企业资源整合与敏捷响应新路径
  • 25/2/16 <算法笔记> DirectPose
  • 我们来学HTTP/TCP -- 另辟蹊径从响应入手
  • 基于状态观测器和物联网基础设施的智能电网高速孤岛检测
  • Ubuntu终端的常用快捷键
  • 【网络】协议与网络版计算器
  • git cherry-pick,需要git commit、git push么?
  • c语言-链表习题
  • 【C】链表算法题7 -- 环形链表||
  • matlab汽车动力学半车垂向振动模型
  • Mac 部署Ollama + OpenWebUI完全指南
  • 第三十三周学习周报
  • 洛谷 P2894 USACO08FEB Hotel 题解
  • C语言----共用体
  • 1、云原生写在前面
  • 高并发系统-性能指标的判断
  • prompt技术结合大模型 生成测试用例
  • transformer(4):FFN 编码器块
  • Hutool - Cron:强大的定时任务模块
  • 思政课也精彩,“少年修齐讲堂”开讲《我的中国“芯”》
  • 426.8万人次!长三角铁路创单日客发量历史新高
  • 李强签署国务院令,公布修订后的《中华人民共和国植物新品种保护条例》
  • 韩国代总统、国务总理韩德洙宣布辞职,将择期宣布参选总统
  • 韩国代总统、国务总理韩德洙宣布辞职
  • 美国季度GDP时隔三年再现负增长,特朗普政府关税政策对美国经济负面影响或将持续