Swift 领域背景搜索

Swift 领域背景搜索,swift,realm,background-thread,Swift,Realm,Background Thread,我的应用程序中有一个领域数据库,包含约2000个用户的列表 tableview显示这些用户,搜索栏允许对他们进行筛选(每个用户的6个不同属性)。 这个操作阻塞了UI,所以我把它放在后台线程中 现在好多了,但我不是100%确定这是最好的方法 如果您有更好的解决方案,您能提出其他解决方案吗 以下是我使用的示例代码: func filterUsers(searchText:String,completion: (result: Array<User>) -> ()){ va

我的应用程序中有一个领域数据库,包含约2000个用户的列表

tableview显示这些用户,搜索栏允许对他们进行筛选(每个用户的6个不同属性)。 这个操作阻塞了UI,所以我把它放在后台线程中

现在好多了,但我不是100%确定这是最好的方法

如果您有更好的解决方案,您能提出其他解决方案吗

以下是我使用的示例代码:

func filterUsers(searchText:String,completion: (result: Array<User>) -> ()){

    var IIDS = Array<String>()

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in

        let predicate1 = NSPredicate(format: "firstName contains[c] %@", searchText)
        let predicate2 = NSPredicate(format: "lastName contains[c] %@", searchText)

        let bgRealm = try! Realm()
        bgRealm.beginWrite()

        //Filter the whole list of users
        var results = Array(bgRealm.objects(User)).filter {
            //One user object by one
            let usr:User = $0
            //Reset the value by default
            usr.searchResultField = ""

            if predicate1.evaluateWithObject(usr) {
                usr.searchResultField = "firstNameORlastName"
                return true
            }
            else if predicate2.evaluateWithObject(usr) {
                usr.searchResultField = "IID"
            }

            return false
        };

        try! bgRealm.commitWrite()

        for usr in results {
            IIDS.append("'\(usr.IID)'")
        }

        results.removeAll()

        dispatch_async(dispatch_get_main_queue(), { () -> Void in

            let realm = try! Realm()
            let foundUsers = Array(realm.objects(User).filter("IID IN {\(IIDS.joinWithSeparator(","))}"))
            IIDS.removeAll()
            completion(result: foundUsers)
        })
    })
}
func过滤器用户(searchText:String,completion:(result:Array)->()){
var IIDS=Array()
dispatch\u async(dispatch\u get\u global\u queue(dispatch\u queue\u PRIORITY\u DEFAULT,0),{()->Void in
let predicate1=NSPredicate(格式:“firstName包含[c]]@”,searchText)
let predicate2=NSPredicate(格式:“lastName包含[c]]@”,searchText)
让bgream=try!Realm()
bgRealm.beginWrite()
//过滤整个用户列表
var results=Array(bgream.objects(User)).filter{
//一个用户对象一个用户对象
让usr:User=$0
//默认情况下重置该值
usr.searchResultField=“”
如果谓词1.evaluateWithObject(usr){
usr.searchResultField=“firstNameORlastName”
返回真值
}
否则如果谓词2.evaluateWithObject(usr){
usr.searchResultField=“IID”
}
返回错误
};
试试!bgRealm.commitWrite()
usr在结果中的应用{
IID.追加(“\(usr.IID)”)
}
results.removeAll()
dispatch\u async(dispatch\u get\u main\u queue(),{()->Void in
让realm=try!realm()
让foundUsers=Array(realm.objects(User.filter)({\(IIDS.joinWithSeparator(“,”)})中的IID)
IIDS.removeAll()
完成(结果:foundUsers)
})
})
}

将对象全部拉入内存后过滤对象(通过将
结果
转换为
数组
)。如果让Realm处理过滤,您的性能会大大提高。为此,您需要能够通过谓词进行所有查询,这些谓词可以组合为一个或复合谓词

此外,我还避免将匹配字段存储在对象中以分离关注点,因为这些值是瞬态的。只有当这些对象保存在内存中时,才需要它们

除此之外,我建议为
IID
使用主键,然后逐个检索一个对象,而不是构建一个包含所有id的大型谓词

总而言之,这就是我解决问题的方法:

func filterUsers(searchText:String, completion: (result: Array<(user: User, field: String)>) -> ()) {   
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
        var predicates = [
          "firstName": NSPredicate(format: "firstName contains[c] %@", searchText)
          "lastName":  NSPredicate(format: "lastName contains[c] %@", searchText)
        ]
        let compoundPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: Array(predicates.values))

        let bgRealm = try! Realm()

        // Filter the whole list of users
        let results = bgRealm.objects(User).filter(compoundPredicate)

        // Find out which field is matching
        let idsAndFields: [(IID: String, field: String)] = results.flatMap {
            for (field, predicate) in predicates {
                if predicate.evaluateWithObject($0) {
                    return (IID: $0.IID, field: field)
                }
            }
            return nil
        }

        dispatch_async(dispatch_get_main_queue()) {
            let realm = try! Realm()
            let result = idsAndFields.flatMap {
                if let user = realm.objectForPrimaryKey($0.IID) {
                    return (user: user, field: $0.field)
                } else {
                    return nil
                }
            }
            completion(result: result)
        })
    }
}
func filterUsers(searchText:String,completion:(结果:数组)->()){
调度异步(调度获取全局队列(调度队列优先级默认为0)){
变量谓词=[
“firstName”:NSPredicate(格式:“firstName包含[c]]@”,搜索文本)
“lastName”:NSPredicate(格式:“lastName包含[c]%@”,搜索文本)
]
让compoundPredicate=NSCompoundPredicate(或PredicateWithSubPredicates:Array(predicates.values))
让bgream=try!Realm()
//过滤整个用户列表
让结果=bgream.objects(用户).filter(复合谓词)
//找出匹配的字段
让idsAndFields:[(IID:String,field:String)]=results.flatMap{
谓词中的(字段,谓词){
if谓词.evaluateWithObject($0){
返回(IID:$0.IID,字段:字段)
}
}
归零
}
dispatch\u async(dispatch\u get\u main\u queue()){
让realm=try!realm()
让结果=idsAndFields.flatMap{
如果let user=realm.objectForPrimaryKey($0.IID){
返回(用户:用户,字段:$0.字段)
}否则{
归零
}
}
完成(结果:结果)
})
}
}