首页 > 解决方案 > 如何在 SwiftUI 中读取和过滤大型 Realm 数据集?

问题描述

我在领域数据库中存储了约 100.000 个字典条目,并希望显示它们。此外,我想通过搜索字段过滤它们。现在我遇到了一个问题:尽管我尝试对搜索进行去抖动,但搜索功能确实效率低下。

查看型号:

class DictionaryViewModel : ObservableObject {

    let realm = DatabaseManager.sharedInstance

    @Published var entries: Results<DictionaryEntry>?
    @Published var filteredEntries: Results<DictionaryEntry>?
    @Published var searchText: String = ""
    @Published var isSearching: Bool = false
    var subscription: Set<AnyCancellable> = []
    
    init() {
        $searchText
            .debounce(for: .milliseconds(800), scheduler: RunLoop.main) // debounces the string publisher, such that it delays the process of sending request to remote server.
            .removeDuplicates()
            .map({ (string) -> String? in
                if string.count < 1 {
                    self.filteredEntries = nil
                    return nil
                }

                return string
            })
            .compactMap{ $0 } 
            .sink { (_) in   
            } receiveValue: { [self] (searchField) in
                filter(with: searchField)
            }.store(in: &subscription)

        self.fetch()
}

    public func fetch(){
        self.entries = DatabaseManager.sharedInstance.fetchData(type:   DictionaryEntry.self).sorted(byKeyPath: "pinyin", ascending: true)
        self.filteredEntries = entries
    }

    public func filter(with condition: String){
        self.filteredEntries = self.entries?.filter("pinyin CONTAINS[cd] %@", searchText).sorted(byKeyPath: "pinyin", ascending: true)
    }

在我的视图中,我只是filteredEtries在 ScrollView 中显示

去抖动对于像“hello”这样的短文本输入效果很好,但是当我过滤“这是一个非常长的字符串”时,我的 UI 会冻结。我不确定我的去抖动功能是否有问题,或者我处理数据过滤的方式非常低效。

编辑:我注意到 UI 冻结,尤其是当结果为空时。

编辑 2: .fetchData() 函数就在这里:

func fetchData<T: Object>(type: T.Type) -> Results<T>{
    let results: Results<T> = realm.objects(type)
    return results
}

所有领域对象都有一个主键。结构如下所示:

@objc dynamic var id: String = NSUUID().uuidString
@objc dynamic var character: String = ""
@objc dynamic var pinyin: String = ""
@objc dynamic var translation: String = ""

override class func primaryKey() -> String {
    return "id"
}

编辑 3:过滤后的结果以这种方式显示:

ScrollView{
    LazyVGrid(columns: gridItems, spacing: 0){
                    if (dictionaryViewModel.filteredEntries != nil)  {
                                 ForEach(dictionaryViewModel.filteredEntries!){ entry in
                                    Text("\(entry.translation)")
                        
                        }
                    } else {
                        Text("No results found")
                    } 
                }

标签: swiftuirealm

解决方案


推荐阅读