I\'m following this SwiftUI tutorial and downloaded the project files.
I built and ran the complete project without any modifications. In the app, if I:
Well, actually it is SwiftUI defect, the View being out of view hierarchy must not be refreshed (ie. body
called) - it should be updated right after next appearance. (I submitted feedback #FB7659875, and recommend to do the same for everyone affected - this is the case when duplicates are better)
Meanwhile, below is possible temporary workaround (however it will continue work even after Apple fix the issue, so it is safe). The idea is to use local view state model as intermediate between view and published property and make it updated only when view is visible.
Provided only corrected view to be replaced in mentioned project.
Tested with Xcode 11.4 / iOS 13.4 - no unexpected "jump back"
struct LandmarkList: View {
@EnvironmentObject private var userData: UserData
@State private var landmarks = [Landmark]() // local model
@State private var isVisible = false // own visibility state
var body: some View {
NavigationView {
List {
Toggle(isOn: $userData.showFavoritesOnly) {
Text("Show Favorites Only")
}
ForEach(landmarks) { landmark in
if !self.userData.showFavoritesOnly || landmark.isFavorite {
NavigationLink(
destination: LandmarkDetail(landmark: landmark)
.environmentObject(self.userData)
) {
LandmarkRow(landmark: landmark)
}
}
}
}
.onReceive(userData.$landmarks) { array in // observe external model
if self.isVisible {
self.landmarks = array // update local only if visible
}
}
.onAppear {
self.isVisible = true // track own state
self.landmarks = self.userData.landmarks
}
.onDisappear { self.isVisible = false } // track own state
.navigationBarTitle(Text("Landmarks"))
}
}
}
this happens because in the "main" list you toggled to "show only favorites". then you change in the detail the favorites (so it is no favorite landmark anymore) and because in swiftui the source of truth was changed (favorite) this item was removed from the main list and so it cannot be shown in the detail anymore because it is no member of the main list anymore, so the detail view just navigates back and show the favorite items only.