swiftui - SwiftUI NavigationLink 在删除然后插入新的 ForEach 元素后中断
问题描述
出于某种原因,我的 NavigationLink 在特定情况下中断:
给定下面的代码,这里是重现的步骤:
- 点击登录,将帐户插入列表
- 回击以弹出堆栈
- 向左滑动并删除,删除列表的第一个元素
- 再次点击登录(应该推入堆栈但没有)
- 点击第一行(应该推到堆栈上但没有)
这是代码:
import SwiftUI
class Account: ObservableObject, Identifiable, Equatable, Hashable {
let id: String
init(id: String) {
self.id = id
}
static func == (lhs: Account, rhs: Account) -> Bool {
return lhs.id == rhs.id
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
class AccountManager: ObservableObject {
@Published private (set) var isLoading: Bool = false
@Published private (set) var accounts: [Account] = []
init() {
load()
}
func load() {
isLoading = true
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) {
self.accounts = [ Account(id: UUID().uuidString) ]
self.isLoading = false
}
}
func add(account: Account) {
accounts.insert(account, at: 0)
}
func delete(at offsets: IndexSet) {
accounts.remove(atOffsets: offsets)
}
}
struct AccountManagerEnvironmentKey: EnvironmentKey {
static var defaultValue: AccountManager = AccountManager()
}
extension EnvironmentValues {
var accountManager: AccountManager {
get { return self[AccountManagerEnvironmentKey.self] }
set { self[AccountManagerEnvironmentKey.self] = newValue }
}
}
struct ContentView: View {
@Environment(\.accountManager) var accountManager
@State var isLoading: Bool = false
@State var accounts: [Account] = []
@State var selectedAccount: Account? = nil
var body: some View {
NavigationView() {
ZStack {
List {
ForEach(accounts) { account in
NavigationLink(
destination: Text(account.id),
tag: account,
selection: $selectedAccount
) {
Text(account.id)
}
}
.onDelete(perform: { offsets in
accountManager.delete(at: offsets)
})
}
if isLoading {
ProgressView("Loading...")
}
}
.navigationBarTitle("Accounts", displayMode: .inline)
.toolbar(content: {
ToolbarItem(placement: .primaryAction) {
Button("Sign In") {
let newAccount = Account(id: UUID().uuidString)
accountManager.add(account: newAccount)
selectedAccount = newAccount
}
}
})
.onReceive(accountManager.$isLoading) { value in
isLoading = value
}
.onReceive(accountManager.$accounts) { value in
accounts = value
}
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
如果我更改按钮操作来执行此操作,它会起作用:
accountManager.add(account: newAccount)
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
selectedAccount = newAccount
}
但这似乎是一个巨大的黑客攻击。
解决方案
推荐阅读
- python - 如何解决此 KeyError?
- c - c中的“无效声明”是什么意思?
- python - 如何使默认的 matplotlib 光标“+”跨越整个 x 轴?
- node.js - 如何有效地将所有子数组与相关 id 组合并删除所有重复对象
- ionic-framework - 如何使用 IONIC 4 在后台模式下流式传输音频
- python - Python:无法导入已安装的模块 pdpbox
- c# - 如何将带有本地安装的 MongoDB 的 Asp.net 核心 Web api 部署到 Microsoft Azure?
- javascript - Vuetify v-combobox,勾选一个框后,删除文本
- python - 在批处理脚本中安装 Python + Django
- python - 如何使用 python 在没有 WASAPI 的情况下挂钩输出音频?