SwiftUI可观察对象无法更新UI

时间:2019-11-08 03:52:51

标签: ios swift swiftui

我有一个可观察的对象,该对象从视图上的onAppear动作加载银行列表。进行更改后,我退出视图,然后返回到调用loadBankMembers的视图,但这些更新未反映在UI中。如果我退出然后回来,那么更新将得到反映。

import SwiftUI

struct BankMembersView: View {
    @EnvironmentObject var userData: UserData

    var body: some View {
        ZStack {
            if userData.showPlaidModal {
                PlaidView()
            }

            List {
                ForEach(userData.bankMembers) { bankMember in
                    BankMemberRowView(bankMember: bankMember)
                }
            }
        }
        .onAppear(perform: { self.userData.loadBankMembers() })
        .navigationBarTitle("Bank Accounts")
        .navigationBarItems(trailing:
            Button(action: { self.userData.showPlaidModal = true }) {
                Text("Add")
            }
        )
    }
}
import SwiftUI
import Combine

final class UserData: ObservableObject  {
    let objectWillChange = ObservableObjectPublisher()

    let apollo = Apollo()

    var bankMembers: [BankMember] = [] {
        willSet { self.objectWillChange.send() }
    }

    func loadBankMembers() {
        apollo.client.fetch(query: ListBankMembersQuery(), cachePolicy: .fetchIgnoringCacheCompletely) { result in
            guard let data = try? result.get().data else { return }
            var bankMembers: [BankMember] = []

            for bankMemberData in data.bankMembers ?? [] {
                var bankAccounts: [BankAccount] = []

                for bankAccountData in bankMemberData?.bankAccounts ?? [] {
                    if let bankAccountid = bankAccountData?.id {
                        let bankAccount = BankAccount(id: bankAccountid, name: bankAccountData?.name ?? "", sync: bankAccountData?.sync ?? false)
                        bankAccounts.append(bankAccount)
                    }
                }

                if let id = bankMemberData?.id {
                    let bankMember = BankMember(id: id, name: bankMemberData?.name ?? "", status: bankMemberData?.status, bankAccounts: bankAccounts)
                    bankMembers.append(bankMember)
                }
            }

            self.bankMembers = bankMembers
        }
    }
}

我尝试在加载开始时设置UserData.banksMembers = [],但随后因以下错误而崩溃:

2019-11-07 20:51:58.191689-0700 Spendable[5839:255244] [TableView] Warning once only: UITableView was told to layout its visible cells and other contents without being in the view hierarchy (the table view or one of its superviews has not been added to a window). This may cause bugs by forcing views inside the table view to load and perform layout without accurate information (e.g. table view bounds, trait collection, layout margins, safe area insets, etc), and will also cause unnecessary performance overhead due to extra layout passes. Make a symbolic breakpoint at UITableViewAlertForLayoutOutsideViewHierarchy to catch this in the debugger and see what caused this to occur, so you can avoid this action altogether if possible, or defer it until the table view has been added to a window. Table view: <_TtC7SwiftUIP33_BFB370BA5F1BADDC9D83021565761A4925UpdateCoalescingTableView: 0x7fe05689fa00; baseClass = UITableView; frame = (0 0; 0 0); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x600000813990>; layer = <CALayer: 0x60000064be20>; contentOffset: {0, 0}; contentSize: {0, 0}; adjustedContentInset: {0, 0, 0, 0}; dataSource: <_TtGC7SwiftUIP13$7fff2c6b223419ListCoreCoordinatorGVS_20SystemListDataSourceOs5Never_GOS_19SelectionManagerBoxS2___: 0x7fe0564235c0>>
2019-11-07 20:51:58.191948-0700 Spendable[5839:255244] *** Assertion failure in -[_TtC7SwiftUIP33_BFB370BA5F1BADDC9D83021565761A4925UpdateCoalescingTableView _endCellAnimationsWithContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKitCore_Sim/UIKit-3900.12.15/UITableView.m:2039
2019-11-07 20:51:58.198956-0700 Spendable[5839:255244] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete section 0, but there are only 0 sections before the update'

1 个答案:

答案 0 :(得分:1)

您错过了 @Published 个var bankMembers。让我展示一个简单的示例(无法使用您的代码,所以写了类似的东西):

final class UserData: ObservableObject  {

    @Published var bankMembers: [String] = []

    func loadBankMembers() {
        bankMembers.append("Steve")
        bankMembers.append("Bob")
    }

    func updateBankMembers() {
        bankMembers.append("John")
        bankMembers.append("Ann")
    }
}
struct BankMembersView: View {
    @EnvironmentObject var userData: UserData

    var body: some View {

        NavigationView {
            List {
                ForEach(userData.bankMembers, id: \.self) { bankMember in
                    Text(bankMember)
                }
            }
            .onAppear(perform: { self.userData.loadBankMembers() })
            .navigationBarTitle("Bank Accounts")
            .navigationBarItems(trailing:
                Button(action: { self.userData.updateBankMembers() }) {
                    Text("Add")
                }
            )
        }
    }
}

,开始时您将拥有: enter image description here

在按下“添加”按钮后: enter image description here

P.S。为您的情况找到合适的article,以获取更多信息