SwiftUI的@EnvironmentObject是一个强大的工具,它允许你在多个视图之间共享数据(使用一个可观察对象)。当你有一个复杂的视图层次结构,并且需要在没有直接连接的视图之间共享相同的可观察对象时,它特别有用。
创建ObservableObject协议类
要使用环境对象,首先需要创建一个符合ObservableObject
协议的ObservableObject
类,这个类将保存我们希望在视图之间共享的数据。并将可以观察的属性使用 @Published 属性包装器声明,不然访问和修改该属性可能会导致app崩溃!例如:
Swift
//
// Model.swift
// SwiftBook
//
// Created by song on 2024/7/11.
//
import Foundation
// 创建模型类
class Person: ObservableObject {
@Published var id: Int = 0
@Published var manList: [Man] = [
Man(index: 1, name: "王思聪", avator: "xigua", content: "好好"),
Man(index: 2, name: "王健林", avator: "liulian", content: "你好"),
Man(index: 3, name: "马云", avator: "taozi", content: "今天"),
Man(index: 4, name: "马化腾", avator: "default", content: "天气"),
Man(index: 5, name: "王亮", avator: "juzi", content: "真"),
Man(index: 6, name: "王伦", avator: "putao", content: "不累"),
]
}
// 创建结构体
struct Man: Identifiable {
var id = UUID()
var index: Int
var name: String
var avator: String
var content: String
}
引入协议类对象
引入这个全局对象的地方有两个地方需要注意:
1.app入口函数的视图中(app启动的时候要保证全局有这个对象,不然会崩溃)
2.要观察全局对象的页面预览视图中(要保证预览页面可以访问到全局对象,不然会崩溃,无法预览或者修改全局对象的属性。即便你在app入口函数设置了,但是预览模式不会走这个入口函数,所以就没办法使用这个入口函数的全局对象)
页面视图修改和访问全局对象
在页面视图中,可以通过声明的@EnvironmentObject var person: Person对象来访问这个全局对象,并通过person.id = 3 的形式来给属性赋值(注意需要将该属性使用@Published属性包装器声明),而且修改后的值,在另外一个页面视图中也是可以成功访问到的。
注意事项
1.使用前一定要在环境变量中添加一个全局对象.environmentObject(Person())
比如你在当前视图中要使用预览功能预览当前页面,就要给当前页面的#Preview函数中添加
2.即便你在App入口函数中添加了这个对象,但是你却在预览中使用这个全局对象,但是你却没有在预览的视图中添加.environmentObject(Person()),程序依然会报错并崩溃!因为预览模式下没有走App的入口函数,所以视图中就没有这个全局对象
3.如果需要向环境中添加多个对象,则应该添加多个.environmentObject
修饰符,一个一个的添加即可。
Swift
struct EnvironmentObjectDemo: View {
@StateObject var gameSettings = GameSettings()
@StateObject var videoSettings = VideoSettings()
var body: some View {
NavigationView {
......
}
.environmentObject(gameSettings)
.environmentObject(videoSettings)
}
}
4.另外如果创建了两个同类型的ObservableObject
对象,并且依次添加到环境中去,那么最早添加的那个起作用,后添加的无效