簡體   English   中英

@EnvironmentObject 可以與不是視圖的普通結構一起使用嗎?

[英]Can @EnvironmentObject be used with a plain struct that isn't a View?

我在將類信息從一個結構實例傳遞到另一個實例時遇到了麻煩,所以我一直在嘗試解決問題。

這是有效的,因為我正在通過視圖

// phone_testingApp.swift
import SwiftUI

@main
struct phone_testingApp: App {
    
    @ObservedObject var myObservedObject = MyObservedObject()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(myObservedObject)
        }
    }
}
// ContentView.swift

import SwiftUI
import Combine

struct ContentView: View {
    
    var subtract = MinusToObject()
    @EnvironmentObject var myNumber: MyObservedObject
    
    var body: some View {
        VStack{

            Text("The number is \(myNumber.theObservedObjectToPass)")
            
            MinusToObject()
                .environmentObject(myNumber)
        }
    }
}

class MyObservedObject: ObservableObject {
    @Published var theObservedObjectToPass = 5
}

struct MinusToObject: View {
    
    @EnvironmentObject var theObservedObject: MyObservedObject
    
    var body: some View {
        Text("Minus")
            .onTapGesture {
                theObservedObject.theObservedObjectToPass -= 1
            }
    }
}

但如果我嘗試類似的東西,只是一個不符合 View 這樣的普通結構

import SwiftUI
import Combine

struct ContentView: View {
    
    var subtract = MinusToObject()
    @EnvironmentObject var myNumber: MyObservedObject
    
    var body: some View {
        VStack{

            Text("The number is \(myNumber.theObservedObjectToPass)")
            
            Text("Minus")
                .onTapGesture {
                    subtract.subtractIt()
                }
        }
    }
}

class MyObservedObject: ObservableObject {
    @Published var theObservedObjectToPass = 5
}

struct MinusToObject {
    
    @EnvironmentObject var theObservedObject: MyObservedObject
    
        
            func subtractIt() {
                theObservedObject.theObservedObjectToPass -= 1 //Thread 1: Fatal error: No ObservableObject of type MyObservedObject found. A View.environmentObject(_:) for MyObservedObject may be missing as an ancestor of this view.
            }
}

我收到一個運行時錯誤,這是我在函數調用時注釋的。

我對如何傳遞引用類型的實例感到非常困惑,所以我確定我做錯了很多事情,任何幫助將不勝感激。

這是行不通的,因為EnvironmentObject注入僅在 SwiftUI View層次結構上執行到所有基於子視圖的對象。

如果您希望任何舊對象訪問共享實例,則必須手動創建一個單例並將其注入 SwiftUI 視圖層次結構中。

class MyObservedObject: ObservableObject {
    static let shared = MyObservedObject()
    private init() { }

    @Published var theObservedObjectToPass = 5
}

/// you can use it in a plain object
struct MinusToObject {
    func subtractIt() {
        MyObservedObject.shared.theObservedObjectToPass -= 1 
    }
}

// you can use it in a view
struct ContentView: View {
    var body: some View {
        SomeOtherView()
            .environmentObject(MyObservedObject.shared)
    }
}
@ObservedObject var myObservedObject = MyObservedObject()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(myObservedObject)
        }
    }

這足以讓您在 ContentView 的任何其他子視圖中獲得相同的myObservedObject實例作為environmentObject 唯一的例外是.sheet ,您需要通過使用相同的.environmentObject(envObjInstance)修飾符為sheet內的視圖手動為每個 sheet .environmentObject(envObjInstance)修飾符。

對於不符合視圖的結構,您可以將環境對象實例的包裝值傳遞給它們,對此傳遞的實例的任何更改也將反映在您的視圖中。

如何:

為您的結構聲明一個變量:

struct AnyStruct {

var anEnvironmentObject: EnvironmentObject<TheEnvironmentObjectType>.Wrapper

.
.
.
}

然后在 SwiftUI 視圖中,首先初始化您的結構:

struct someSwiftUIView: View {

@EnvironmentObject var myEnvObj: TheEnvironmentObjectType

var anyStruct: AnyStruct { AnyStruct.init(anEnvironmentObject: $myEnvObject) } 
// notice the dollar sign `$`

}

然后在您的AnyStruct ,您可以更改 environmentObject 中的值,並確保它們也將反映在您的視圖中。 您只需要記住,您需要使用.wrappedValue為環境對象內的變量分配一個新值。 假設您的 environmentObject 中有一個名為observedInteger的變量:

extension AnyStruct {
func changeValueOfObservedIntegerToZero() {
self.anEnvironmentObject.observedInteger.wrappedValue = 0
// notice the `.wrappedValue`
}
}

請注意,這種方法 100% 對我有用,但我不確定是否可以更簡單。 您甚至可能不需要將環境對象的包裝值傳遞給結構體,您可以只傳遞簡單值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM