I have a RealityView that is an earth globe, where I'm adding attachments and also updating how attachments appear, depending on user input.
I pass a @Binding var annotations: [MyAnnotation]
to my view which has a RealityView
as its main body. The annotations are displayed fine using the SwiftUI views defined in the annotations
handler, but they do not update when the annotations in that binding are updated.
My attachments:
handler looks like this:
RealityView { ...
} attachments: {
ForEach($annotations) { $attachment in
AttachmentView(attachment: $attachment)
.tag(attachment.id)
}
}
I also tried without the $
syntax there. Neither leads to an update of the AttachmentView
. Curiously the update
handler also isn't called when the annotations are updated.
I also tried settings a different .id
on the entire thing, but even then it's just using my AttachmentView
as initially configured.
I'm very puzzled by this and would appreciate help. Am I holding this wrong, or is this a bug?
Okay, I've figured out a few things here, in case someone has similar issues:
- I was holding it wrong in that there was an issue with changes not being picked up by the binding. After I fixed that, the
attachments:
handler did get called again. Hooray. - The old
AttachmentView
did stick around though, due to the IDs of my attachments changing when they changed shape. I fixed this by making sure those IDs are stable, and callingcontent.add(...)
again in theupdate:
handler then updated those to the new look.
The remaining issues was to get rid of all attachment entities if they disappear from my Binding. I'm not particularly happy with it, but the solution I came up with, was to collect the IDs and then iterate through all entities to check if their IDs are still in my set:
let allEntities = Array(content.entities)
for entity in allEntities {
if let attachmentEntity = entity as? ViewAttachmentEntity, let id = attachmentEntity.attachment.id as? String, !goodIDs.contains(id) {
content.remove(attachmentEntity)
}
}
Would love to know if there's a better way to do this.