為了解釋這種行為,我構建了一個簡化的專案,它創建了與我的作業專案相同的行為。請記住,我的真實專案比這個更大,并且有更多的限制。
我有一個簡單struct的只有Intas 屬性(命名MyObject)和一個存盤 6 的模型MyObject。
struct MyObject: Identifiable {
let id: Int
}
final class Model: ObservableObject {
let objects: [MyObject] = [
MyObject(id: 1),
MyObject(id: 2),
MyObject(id: 3),
MyObject(id: 4),
MyObject(id: 5),
MyObject(id: 6)
]
}
請注意,在我的真實專案中,Model更復雜(從 JSON 加載)。
然后我有一個FavoritesManager可以添加和洗掉的MyObject收藏夾。它有一個@Publishedids ( Int)陣列:
final class FavoritesManager: ObservableObject {
@Published var favoritesIds = [Int]()
func addToFavorites(object: MyObject) {
guard !favoritesIds.contains(object.id) else { return }
favoritesIds.append(object.id)
}
func removeFromFavorites(object: MyObject) {
if let index = favoritesIds.firstIndex(of: object.id) {
favoritesIds.remove(at: index)
}
}
}
我的App結構創建 Model 和 FavoritesManager 并在我的第一個視圖中注入它們:
@main
struct testAppApp: App {
@StateObject private var model = Model()
@StateObject private var favoritesManager = FavoritesManager()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(model)
.environmentObject(favoritesManager)
}
}
}
現在我有幾個視圖顯示我的物件:
ContentView顯示一個鏈接到ObjectsListView使用NavigationLink和FavoritesView。在我的真實專案中,ObjectsListView不顯示所有物件,只顯示一個選擇(例如按類別)。
struct ContentView: View {
@EnvironmentObject var model: Model
var body: some View {
NavigationView {
VStack {
NavigationLink(
destination: ObjectsListView(objects: model.objects), label: {
Text("List of objects")
}
)
FavoritesView()
.padding()
}
}
}
}
FavoritesView顯示當前所選收藏夾的 ID。FavoritesManager當添加/洗掉收藏夾時,它會觀察更新其主體。
重要提示:它會創建一個新NavigationLink的收藏詳細資訊視圖。如果您洗掉此鏈接,則不會發生錯誤。
struct FavoritesView: View {
@EnvironmentObject var model: Model
@EnvironmentObject var favoritesManager: FavoritesManager
var body: some View {
HStack {
Text("Favorites:")
let favoriteObjects = model.objects.filter( { favoritesManager.favoritesIds.contains($0.id) })
ForEach(favoriteObjects) { object in
NavigationLink(destination: DetailsView(object: object), label: {
Text("\(object.id)")
})
}
}
}
}
ObjectsListView只是顯示物件并鏈接到DetailsView.
struct ObjectsListView: View {
@State var objects: [MyObject]
var body: some View {
List {
ForEach(objects) { object in
NavigationLink(destination: DetailsView(object: object), label: { Text("Object \(object.id)")})
}
}
}
}
DetailsView顯示物件詳細資訊并添加一個按鈕以將當前物件添加/洗掉為收藏。如果您按下星號,當前物件將被添加為收藏(如預期)并將FavoritesView更新以顯示/洗掉此新 id(如預期)。
But here is the bug: as soon as you press the star, current view (DetailsView) disappears and it goes back (without animation) to previous view (ObjectsListView).
struct DetailsView: View {
@EnvironmentObject var favoritesManager: FavoritesManager
@State var object: MyObject
var body: some View {
VStack {
HStack {
Text("You're on object \(object.id) detail page")
Button(action: {
if favoritesManager.favoritesIds.contains(object.id) {
favoritesManager.removeFromFavorites(object: object)
},
else {
favoritesManager.addToFavorites(object: object)
}
}, label: {
Image(systemName: favoritesManager.favoritesIds.contains(object.id) ? "star.fill" : "star")
.foregroundColor(.yellow)
})
}
Text("Bug is here: if your press the star, it will go back to previous view.")
.font(.caption)
.padding()
}
}
}
You can download complete example project here.
You may ask why I don't display objects list in ContentView directly. It is because of my real project. It displays objects classified by categories in lists. I have reproduce this behavior with ObjectsListView.
I also need to separated Model and FavoritesManager because in my real project I don't want that my ContentView's body is updated everytime a favorite is added/removed. That's why I have moved all favorites displaying in FavoritesView.
我相信這個問題的發生是因為我NavigationLinks在 current 中添加/洗掉NavigationView。看起來它正在重新加載整個導航層次結構。但我不知道如何獲得DetailsView具有相同視圖層次結構的預期結果(按下星形按鈕時保持不變)。我可能在某個地方做錯了什么......
uj5u.com熱心網友回復:
添加.navigationViewStyle(.stack)到您NavigationView的ContentView. 這樣,您的代碼對我來說效果很好,我可以按星號DetailsView,它仍然顯示。它不會回傳到先前的視圖。使用 macos 12.2、Xcode 13.2,針對 ios 15.2 和 macCatalyst 12.1。在真實設備上測驗。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/407087.html
標籤:
