I have this class which calls an API every 3 seconds (using a timer) and saves the result in the @Published
array named items
:
public class ApiAdapter: ObservableObject {
@Published var items = [Item]()
init() {
api = Api(...)
Timer.scheduledTimer(withTimeInterval: 3, repeats: true) { timer in
api.getItems() { items in
if let _items = items {
self.items = _items
}
}
}
}
}
The ApiAdapter is used throughout the entire app so I decided to make it an @EnvironmentObject
.
In the main view of my app I'm accessing the apiAdapter.items
array for displaying it in a list like so:
struct MainListView: View {
@EnvironmentObject var apiAdapter: ApiAdapter
var body: some View {
NavigationView {
List {
ForEach(apiAdapter.items, id: \.hash) { i in
Text(i.name)
...
}
}
.navigationBarItems(trailing:
Menu {
Picker(selection: $category, label: Text("Filter")) {
Text("Category 1").tag(1)
Text("Category 2").tag(2)
Text("Category 3").tag(3)
}
} label: {
Image(systemName: "line.horizontal.3.decrease.circle")
.imageScale(.large)
}
}
}
}
In MainListView I have also some Menu
s in the navigationBar
which get closed every time the apiAdapter
updates the items
variable, so it makes it hard to use them.
How is it possible to update only the list and not the entire view? or even better how is it possible to update only the items that changed in the last api call?
Remove the EnvironmentObject
from your MainListView. Create a new View for the List only like this:
struct ListView : View {
@EnvironmentObject var apiAdapter: ApiAdapter
var body : some View {
List {
ForEach(apiAdapter.items, id: \.hash) { i in
Text(i.name)
}
}
}
}
Now your subview only updates, while your main view remains the same and the Menu remains opened.
And your MainListView as follows:
struct MainListView: View {
var body: some View {
NavigationView {
ListView() //<< here comes your ListView which refreshes independent
.navigationBarItems(trailing:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.