在我的应用程序中,我需要通过轻触按钮来重新实例化一个@EnvironmentObject。哪里是做这件事的合适地点呢?
这是我的视图截图-在存档对象列表中,我希望拥有不可变的对象。因此,当我点击Archive Object时,我希望将当前对象添加到数组中,并创建一个新的当前对象。

该应用程序的简化版本如下所示。
我在SceneDelegate中实例化了对象
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
var myObject = MyObject()
let myObjects = MyObjects()
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let contentView = ContentView()
.environmentObject(myObject)
.environmentObject(myObjects)
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
//.....
}以下是我的模型:
class MyObject: ObservableObject, Identifiable {
@Published var id = UUID()
}
class MyObjects: ObservableObject {
@Published var values: [MyObject] = [
MyObject(),
MyObject()
]
}在我看来,我需要将当前对象放到一个(存档)数组中,然后创建一个新的当前对象进行操作。这是我正在尝试的:
struct ContentView: View {
@EnvironmentObject var currentObject: MyObject
@EnvironmentObject var objects: MyObjects
var sceneDelegate: UISceneDelegate {
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let sd = windowScene.delegate as? SceneDelegate else { fatalError() }
return sd
}
var body: some View {
VStack {
Form {
Section(header: Text("Current Object")) {
Text(currentObject.id.uuidString)
}
Section(header: Text("Archived Objects")) {
List(objects.values, id: \.id) { object in
Text(object.id.uuidString)
}
Button(action: {
self.objects.values.append(self.currentObject)
// as the environment object is get only, I cannot reinstantiate it here...
// self.currentObject = MyObject()
}) {
Text("Archive Object")
}
}
}
Spacer()
}
}
}发布于 2020-05-16 03:50:40
这是一个解决方案。请参阅内联注释。
使用Xcode11.4/ iOS 13.4进行测试

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
// Usage
ContentView(current: MyObject())
.environmentObject(MyObjects())
}
}
struct ContentView: View {
@EnvironmentObject var objects: MyObjects
@State private var current: MyObject // tracks current
init(current: MyObject) {
_current = State(initialValue: current)
}
var body: some View {
// rebuilt on *current* changed
ContentInnerView(current: $current)
.environmentObject(current)
}
struct ContentInnerView: View {
@Binding var current: MyObject // change current
@EnvironmentObject var objects: MyObjects
@EnvironmentObject var currentObject: MyObject
init(current: Binding<MyObject>) {
_current = current
}
var sceneDelegate: UISceneDelegate {
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let sd = windowScene.delegate as? SceneDelegate else { fatalError() }
return sd
}
var body: some View {
VStack {
Form {
Section(header: Text("Current Object")) {
Text(currentObject.id.uuidString)
}
Section(header: Text("Archived Objects")) {
List(objects.values, id: \.id) { object in
Text(object.id.uuidString)
}
Button(action: {
self.objects.values.append(self.currentObject)
self.current = MyObject() // << works !!
}) {
Text("Archive Object")
}
}
}
Spacer()
}
}
}
}https://stackoverflow.com/questions/61827121
复制相似问题