SwiftUI NavigationLink прерывается после удаления и вставки нового элемента ForEach

По какой-то причине моя NavigationLink не работает в определенных обстоятельствах:

Учитывая приведенный ниже код, выполните следующие действия:

  • Нажмите «Войти», чтобы добавить учетную запись в список.
  • Ударьте, чтобы открыть стек
  • Проведите пальцем влево и нажмите Delete, чтобы удалить первый элемент списка.
  • Снова нажмите "Войти" (должно быть помещено в стек, но этого не происходит)
  • Коснитесь первой строки (должна надавить на стопку, но не нажимает)

Вот код:

      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
                        }

Но это похоже на серьезный взлом.

0 ответов

Другие вопросы по тегам