Ryan
Ryan

Reputation: 4884

Update LazyVGrid list

I have a LazyVGrid list which need to be updated whenever a data is updated. The data is in a singleton class.

class BluetoothManager: NSObject {
    static let shared = BluetoothManager()
    @objc dynamic private(set) var stations: [BHStation] = []
}

And the list is

var body: some View {
    let columns: [GridItem] = Array(repeating: .init(.flexible()), count: UIDevice.current.userInterfaceIdiom == .pad ? 2 : 1)
    ScrollView {
        LazyVGrid(columns: columns, alignment: .center, spacing: 10, pinnedViews: [], content: {
            ForEach(BluetoothManager.shared.stations, id: \.peripheral.identifier) { item in
                NavigationLink(destination: DetailView()) {
                    MainCell()
                } 
            }
        })
    }
}

I tried to use ObservableObject with @Published, or to use @State/@Binding but none of them worked.

How can I make the list get updated whenever stations is get updated? @objc dynamic is necessary to be used in the other UIKit classes.

Upvotes: 0

Views: 1407

Answers (1)

jnpdx
jnpdx

Reputation: 52565

In order for your SwiftUI View to know to update, you should use an ObservableObject with a @Published property and store it as a @ObservedObject or @StateObject:

class BluetoothManager: NSObject, ObservableObject {
    static let shared = BluetoothManager()
    private override init() { }
    @Published var stations: [BHStation] = []
}
struct ContentView : View {
    @ObservedObject private var manager = BluetoothManager.shared
    
    var body: some View {
        let columns: [GridItem] = Array(repeating: .init(.flexible()), count: UIDevice.current.userInterfaceIdiom == .pad ? 2 : 1)
        ScrollView {
            LazyVGrid(columns: columns, alignment: .center, spacing: 10, pinnedViews: [], content: {
                ForEach(manager.stations, id: \.peripheral.identifier) { item in //<-- Here
                    NavigationLink(destination: DetailView()) {
                        MainCell()
                    }
                }
            })
        }
    }
}

The @Published may interfere with your @objc requirement, but since you haven't given any information on how you use it in UIKit or why it's necessary, it's not possible to say directly what the fix is. You may need a different setter to use when interacting with it in UIKit.

Also, be aware that @Published won't update as expected unless the model type it is storing (BHStation) is a struct. If it's a class, you may need to call objectWillChange directly to get the @Published publisher to trigger correctly.

Upvotes: 1

Related Questions