Hi I have 2 views and an Immersive space. 1st and 2nd views are display in a TabView
I open my ImmersiveSpace from a button in the 1st view of the tab. Then When I go to 2nd TabView
I want to show an attachment
in my Immersive space. This attachment
should be visible in Immersive space only as long as the user os on the 2nd view. This is what I have done so far
struct Second: View {
@StateObject var sharedImageData = SharedImageData()
var body: some View {
VStack {
// other code
} .onAppear() {
Task {
sharedImageData.shouldCameraButtonShouw = true
}
}
.onDisappear() {
Task {
sharedImageData.shouldCameraButtonShouw = false
}
}
}
}
This is my Immersive space
struct ImmersiveView: View {
@EnvironmentObject var sharedImageData: SharedImageData
var body: some View {
RealityView { content, attachments in
// some code
} update: { content, attachments in
guard let controlCenterAttachmentEntity =
attachments.entity(for: Attachments.controlCenter) else { return }
controlCenterentity.addChild(controlCenterAttachmentEntity)
content.add(controlCenterentity)
} attachments: {
if sharedImageData.shouldCameraButtonShouw {
Attachment(id: Attachments.controlCenter) {
ControlCenter()
}
}
}
}
}
And this is my Observable
class
class SharedImageData: ObservableObject {
@Published var takenImage: UIImage? = nil
@Published var shouldCameraButtonShouw: Bool = false
}
My problem is, when I am on Second
view my attachment
never appears. Attachment appears without this if condition. But How can I achieve my goal?
Hello @rands
The value of a property with the @EnvironmentObject
annotation must be supplied by a parent or ancestor view. Additionally, in Second
, you have declared SharedImageData
with the @StateObject
annotation, which creates a brand new instance. This means that when Second
sets sharedImageData.shouldCameraButtonShouw
to true
, it is updating the value of its own SharedImageData
instance, rather than the one inside ImmersiveView
.
To fix this, swap the @StateObject
annotation in Second
with @EnvironmentObject
:
struct Second: View {
@EnvironmentObject var sharedImageData: SharedImageData
var body: some View {
// ...
}
}
Then when you declare Second
, you will need to pass in sharedImageData
via the .environmentObject()
API. You are likely doing this already for ImmersiveView
.
One more thing: I also noticed that in your update
closure, you are adding controlCenterAttachmentEntity
every time this block is called (i.e., when the state changes). This is probably not necessary and may cause other issues in your app. Instead of putting your attachment behind an if
check, create your attachment regardless and move the if check to update, where you can enable/disable the controlCenterAttachmentEntity
to toggle the visibility of your attachment.
Check out the Diorama sample project for an example of how to conditionally show and hide attachments.
Good luck!