SwiftUI 列表标题文本不在原地

问题描述 投票:0回答:0

我遇到一个问题,当我删除一个部分的最后一项时,标题都会短暂地向上移动。使用 Realm 在 SwiftUI 中处理这个问题有技巧吗?当一个项目不是一个部分的最后一行时,这不会发生。仅当该部分被删除时。

带有列表使用部分的选项卡。这是设置标题的地方。

struct HistoryTab: View {
    @EnvironmentObject var realmManager: RealmManager
    @EnvironmentObject var stateModel: StateModel
    
    @Binding var showSideMenu: Bool
    @Binding var showAddSheet: Bool
    
    var toggleSideMenu: ((() -> ())?) -> ()
    @State private var searchText = ""
    
    var body: some View {
        NavigationStack {
            ZStack {
                if realmManager.history?.count ?? 0 > 0 {
                    List {
                        ForEach(realmManager.groupedHistory.indices, id: \.self) { i in
                            if realmManager.groupedHistory[i].count > 0 {
                                Section {
                                    let monthEntries = realmManager.groupedHistory[i]
                                    HistoryRowsView(entries: monthEntries, index: i)
                                } header: {
                                    Text(realmManager.groupedHistory[i].first?.monthYear ?? "")
                                }
                            }
                        }
                    }
                    .listStyle(.automatic)
                } else {
                    VStack {
                        Spacer()
                        Text("Message")
                            .multilineTextAlignment(.center)
                            .font(Font.system(size: 18))
                            .foregroundColor(.secondary)
                        
                        Spacer()
                        Spacer()
                    }
                    .frame(maxWidth: .infinity)
                }
                
            }
            .allowsHitTesting(showSideMenu ? false : true)
            .navigationTitle("History")
            .navigationBarTitleDisplayMode(.large)
            .toolbarBackground(stateModel.showNav, for: .navigationBar)
            .toolbar(stateModel.showTab, for: .tabBar)
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button {
                        toggleSideMenu(nil)
                    } label: {
                        Image(systemName: "line.3.horizontal")
                            .font(.system(size: 18, weight: .regular))
                    }
                }
                
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button {
                        withAnimation {
                            realmManager.addTestHistoryEntry()
                        }
                    } label: {
                        Image(systemName: "plus")
                            .font(.system(size: 18, weight: .medium))
                            .foregroundColor(Color("Burnt_Orange"))
                    }
                }
                
            }
            .accentColor(Color("Burnt_Orange"))
            .background {
                Color.black.opacity(0.025)
            }
            .sheet(isPresented: $showAddSheet) {
                showAddSheet = false
            } content: {
                EditEntrySheet(editType: .add)
                    .interactiveDismissDisabled()
            }
        }
    }
}

每个部分的行视图以及如何删除项目。

struct HistoryRowsView: View {
    @EnvironmentObject var realmManager: RealmManager
    var index: Int
    
    var body: some View {
        if let array = realmManager.groupedHistory.getElement(at: index) {
            ForEach(array) { entry in
                if !entry.isInvalidated {
                    ZStack {
                        HistoryCell(entry: entry)
                        NavigationLink {
                            HistoryDetail(entry: entry)
                        } label: {
                            EmptyView()
                        }
                        .opacity(0.0)
                    }
                }
            }
            .onDelete(perform: deleteEntry)
        }
    }
    
    func deleteEntry(indexSet: IndexSet) {
        guard let offset = indexSet.first else { return }

        let entryRemove = realmManager.groupedHistory[index][offset]
        
        delete(images: entryRemove.images)
        
        if let entryDelete = realmManager.historyArray.first(where: { $0.id == entryRemove.id }) {
            DispatchQueue.main.async {
                realmManager.delete(entryDelete)
            }
        }
    }
    
    func delete(images: MutableSet<String>) {
        for id in images {
            ImageHandler.deleteImage(id: id)
        }
    }
}

具有观察者和历史条目分组的 RealmManager。

class RealmManager: ObservableObject {
    private(set) var localRealm: Realm?
    
    /// History entries
    @Published var history: Results<HistoryEntry>?
    @Published var historySearchFilter = ""
    var historyArray: [HistoryEntry] {
        if let history = history {
            return Array(history)
        } else {
            return []
        }
    }
    var groupedHistory: [[HistoryEntry]] {
        if historySearchFilter.isEmpty {
            return historyArray.group { $0.monthYear }
        } else {
            return historyArray.filter{ ($0.qualifier?.title.lowercased() ?? "").contains(historySearchFilter.lowercased()) }.group { $0.monthYear }
        }
    }
    
    private var historyToken: NotificationToken?
    
    init(name: String) {
        initializeSchema(name: name)
        setupHistoryObserver()
    }
    
    func initializeSchema(name: String) {
        let docDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let realmFileUrl = docDir.appendingPathComponent("\(name).realm")
        let config = Realm.Configuration(fileURL: realmFileUrl, schemaVersion: 0) { migration, oldSchemaVersion in
        }
        Realm.Configuration.defaultConfiguration = config
        
        do {
            localRealm = try Realm()
        } catch {
            print("Error opening default realm", error)
        }
    }
    
    func setupHistoryObserver() {
        guard let realm = localRealm else { return }
        let observedEntries = realm.objects(HistoryEntry.self).sorted(byKeyPath: "date", ascending: false)
        historyToken = observedEntries({ [weak self] _ in
            self?.history = observedEntries
        })
    }
}
swiftui realm swiftui-list
© www.soinside.com 2019 - 2024. All rights reserved.