Mic*_*sky 5 swiftui swiftui-navigationlink
我有一个列表,其中包含推送视图的行。该视图有另一个列表,它推送另一个视图。原来的List,第一个推送的List会随着数据的变化而更新。但是,推送时最后一个视图不会更新。当我向后滑动视图不再更新时,即使它曾经更新过。
HomeView > UserView > ItemView
User 和 Item 是可识别的结构。我试过让它们 Hashable 并使用id: \.self,但这似乎也不起作用。
class App: ObservableObject {
@Published var users = [User]()
}
struct HomeView {
@EnvironmentObject var app: App
var body {
List {
Section {
ForEach(app.users) { user in
NavigationLink(destination: UserView(user: user)) {
Text(user.name)
}
}
}
}
}
}
// Updates fine when `app.users` updates
// Stops updating after going back from ItemView
struct UserView {
let user: User
var body {
List {
Section {
ForEach(user.items) { item in
NavigationLink(destination: ItemView(user: user, item: item)) {
Text(item.name)
}
}
}
}
}
}
/// Does not update when app.users updates
struct ItemView {
let user: User
let item: Item
var body {
List {
Section {
ForEach(item.details) { detail in
Text(detail)
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
经过长时间的搜索,我想出了一些我在互联网其他地方还没有看到的东西。我正在使用父视图中的 @State 初始化我的视图,并使用 onReceive 更新它。此外,onReceive/onAppear 检查该项目是否仍然有效,并在需要时弹出视图。进行 init 来设置状态并将其设为私有可能更正确。
主要原因是删除导致崩溃。这是我为测试更改和删除源而制作的完整示例。
struct Item: Identifiable {
var id: String
var name: String
var accounts: [Account]
}
struct Account: Identifiable {
var id: String
var name: String
}
class App: ObservableObject {
@Published var items: [Item] = [
Item(id: "a", name: "A", accounts: [
Account(id: "1", name: "one"),
Account(id: "2", name: "two"),
Account(id: "3", name: "three")
])
]
}
struct RootView: View {
var body: some View {
NavigationView {
ContentView().environmentObject(App())
}
}
}
struct ContentView: View {
@EnvironmentObject var app: App
var body: some View {
List {
ForEach(app.items) { item in
NavigationLink(destination: ItemView(item: item)) {
Text("\(item.id) - \(item.name)")
}
}
Button(action: { self.app.items[0].name = "XXX" }) {
Text("Change Item Name")
}
Button(action: { self.app.items = [] }) {
Text("Clear")
}
}
}
}
struct ItemView: View {
@Environment(\.presentationMode) var presentationMode
@EnvironmentObject var app: App
@State var item: Item
var body: some View {
List {
Text("\(item.id) - \(item.name)")
ForEach(item.accounts) { account in
NavigationLink(destination: AccountView(item: self.item, account: account)) {
Text("\(account.id) - \(account.name)")
}
}
Button(action: { self.app.items[0].name = "XXX" }) {
Text("Change Item Name")
}
Button(action: { self.app.items[0].accounts[0].name = "AAA" }) {
Text("Change Account Name")
}
Button(action: { self.app.items = [] }) {
Text("Clear")
}
}
.onReceive(app.$items) { items in
guard let item = items.first(where: { $0.id == self.item.id }) else {
self.presentationMode.wrappedValue.dismiss()
return
}
self.item = item
}
.onAppear {
if !self.app.items.contains(where: { $0.id == self.item.id }) {
self.presentationMode.wrappedValue.dismiss()
}
}
}
}
struct AccountView: View {
@Environment(\.presentationMode) var presentationMode
@EnvironmentObject var app: App
@State var item: Item
@State var account: Account
var body: some View {
List {
Text("\(item.id) - \(item.name)")
Text("\(account.id) - \(account.name)")
Button(action: { self.app.items[0].name = "XXX" }) {
Text("Change Item Name")
}
Button(action: { self.app.items[0].accounts[0].name = "AAA" }) {
Text("Change Account Name")
}
Button(action: { self.app.items = [] }) {
Text("Clear")
}
}
.onReceive(app.$items) { items in
guard
let item = items.first(where: { $0.id == self.item.id }),
let account = item.accounts.first(where: { $0.id == self.account.id })
else {
self.presentationMode.wrappedValue.dismiss()
return
}
self.item = item
self.account = account
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1673 次 |
| 最近记录: |