When I create an object, the view is updated, but when I update data inside that object, the view is not updated

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

    @Published var containers: [PostContainer] = []
    // Other code
}
class PostContainer: ObservableObject {
    
    var id: UUID = UUID()
    var timestamp: Date
    var subreddit: String
    var posts: [Post]
    var type: ContainerType
    var active: Bool

    // Init
}
@Model
final class Post: Decodable, ObservableObject {
// Other code
}

In my main view, a network request is made and a PostContainer is created if it doesn't exist. This code works fine, and the view is updated correctly.

let container = PostContainer(timestamp: Date(), subreddit: subreddit, posts: posts, type: .search, active: true)
self.containers.append(container)

If the user wants to see more, they press a button and another request is made. This time, the new data will be added to the PostContainer instead of creating a new one.

if let container = self.containers.first(where: {$0.subreddit == subreddit}) {
    // Update previous container
    container.timestamp = Date()
                    
    print(container.posts.count)
                    
     // Map IDs from container and then remove duplicates
    let existingIDs = Set(container.posts.map { $0.id })
    let filtered    = posts.filter { !existingIDs.contains($0.id) }
                    
                    // Append new post
    container.posts.append(contentsOf: filtered)
    container.active    = true

 }

This code is working fine as well, except for the view is not updating. In the view, PostManager is an @EnvironmentObject. I also have a computed variable to get the post and sort them. I added a print statement to that variable and saw that it wasn't being printed even though more data was being added to the PostContainer. At one point, I created an ID for the List that displays the data and had the code inside PostManager update that ID when it was finished. This of course worked, but it's not ideal.

How can I get the view to update when post are appended inside of PostContainer?

Replies

Well, I resolved it not long after posting. I had to make PostContainer a struct and update the containers themselves using the index. See example below.

if var index = self.containers.firstIndex(where: {$0.subreddit == subreddit}) {
                    // Update previous container
                    self.containers[index].timestamp = Date()
                    self.containers[index].posts     = posts
                    self.containers[index].active    = true
                    
                    print("Updated old container")
                } else {
                    // Create the container
                    // Set to active, because its a new query
                    let container = PostContainer(timestamp: Date(), subreddit: subreddit, posts: posts, type: .search, active: true)
                    self.containers.append(container)
                    print("Created new search container")
                }

I guess because with structs, you're creating a new version of the object when it's updated and @Published is able to see the change. With class, it seems to struggle to know if there's been a change or not.