[英]SwiftUI - Changes in detail view to @fetchRequest pops navigation link view
我有兩種看法。 一種視圖是使用@fetchRequest 從核心數據存儲中獲取的對象(人員)列表。 另一個視圖是詳細視圖,用戶可以通過點擊列表視圖中的人員項目導航到該視圖。 這個想法是用戶可以在詳細視圖中編輯一個人的詳細信息(例如姓名、年齡)。 到目前為止,一切都很好。
關鍵點是列表視圖的設計使得並非所有人都必須從核心數據存儲中獲取。 僅提取滿足特定條件的人。 讓我們假設標准是這個人必須在 30 到 40 歲之間。
我的問題是,當用戶將詳細視圖中的人的年齡更改為不滿足獲取請求標准的某個年齡時(例如,他將年齡從 35 歲更改為 20 歲),詳細視圖將在用戶點擊保存按鈕,托管的 object 上下文保存,由@fetchRequest 在列表視圖中注冊。
我知道會發生這種情況,因為驅動列表視圖的人員的 fetchRequest 發生了變化,因為編輯的人被刪除了,因為他不再滿足 30 到 40 年的要求。 但我不希望在用戶仍在詳細視圖中時發生這種情況。 點擊保存按鈕不應自動彈出詳細視圖。 在使用@fetchRequest 時有什么方法可以防止這種情況發生嗎?
這是導致所描述問題的代碼的精簡版本:
struct PersonList: View {
@FetchRequest var persons: FetchedResults<Person>
init() {
let lowerAge = NSPredicate(format: "%K >= %@", #keyPath(Person.age), 30 as CVarArg)
let upperAge = NSPredicate(format: "%K <= %@", #keyPath(Person.age), 40 as CVarArg)
let agePredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [lowerAge, upperAge])
_persons = FetchRequest(entity: Person.entity(), sortDescriptors: [], predicate: agePredicate)
}
var body: some View {
NavigationView {
ScrollView(showsIndicators: false) {
LazyVStack(spacing: 10) {
ForEach(persons, id: \.id) { person in
NavigationLink(destination: PersonDetail(person: person)) {
Text(person.name)
}
}
}
}
}
}
struct PersonDetail: View {
@Environment(\.managedObjectContext) var viewContext
@State var ageInput: String = ""
var person: Person
var body: some View {
TextField("Enter Age", text: $ageInput)
.onAppear(perform: {
ageInput = "\(person.age)"
})
Button("Save", action: { save() } )
}
}
func save() {
if let age = Int(ageInput) {
viewContext.saveContext()
}
}
}
正如您所指出的, NavigationLink
被彈出是因為底層 model 已從提取請求中刪除。 不幸的是,這意味着您必須將導航鏈接移到列表視圖之外,以便您可以緩存 model,即使它已從獲取結果列表中刪除。
一種方法是將您的 VStack/ScrollView 嵌入到 ZStack 中,並帶有一個隱藏的“單例”導航鏈接和一個跟蹤主動選擇的人的@State 變量:
struct PersonList: View {
@FetchRequest var persons: FetchedResults<Person>
@State private var selectedPerson = Person(entity: Person.entity(), insertInto: nil)
@State private var showPersonDetail = false
var body: some View {
NavigationView {
ZStack {
NavigationLink(destination: PersonDetail(person: selectedPerson), isActive: $showPersonDetail) { EmptyView() }.hidden()
ScrollView(showsIndicators: false) {
LazyVStack(spacing: 10) {
ForEach(persons, id: \.id) { person in
Button(action: {
selectedPerson = person
showPersonDetail = true
}, label: {
// You could hack out the click/tap listener for a navigation link instead of
// emulating its appearance, but that hack could stop working in a future iOS release.
HStack {
Text(person.name)
Spacer()
Image(systemName: "chevron.right")
}
})
}
}
}
}
}
}
將.navigationViewStyle(.stack)
添加到最外層NavigationLink
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.