【问题标题】:Implement search similar to native contacts search?实现类似于原生联系人搜索的搜索?
【发布时间】:2024-04-27 14:00:02
【问题描述】:

在本地联系人应用程序中,当您尝试搜索联系人时,您输入一些字符串,如果联系人名字/姓氏/公司等以该字符串开头,将显示联系人。

为了让事情变得更复杂,您可以输入 Mi Ric 之类的内容,然后搜索会找到 Michael Richardson。 Ric Mi 也会让我得到 Michael Richardson。

我已将联系人记录复制到我的本地核心数据存储中,现在我的第一反应是使用 NSFetchedResultsController 和一些不错的谓词。

但是我将如何处理这个谓词?如果人员记录最多有 3 个单词,我应该用 beginWith 查询每个单词吗?这甚至可以在一个谓词中完成吗?

【问题讨论】:

标签: ios search nspredicate


【解决方案1】:

这是我用于词基谓词的内容:

+ (NSPredicate *)wordBasedPredicateForString:(NSString *)searchString withProperty:(NSString *)property
{

   // searchString = [searchString stringForSearch];
    NSArray *searchStrings = [searchString componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];

    NSMutableArray<NSPredicate *> *subPredicates = [NSMutableArray array];

    for (NSString *string in searchStrings)
        if (![string isEqualToString:@""]) {
            NSString *mainString = [property stringByAppendingString:@" CONTAINS[cd] "];        
            mainString = [NSString stringWithFormat:@"%@ CONTAINS[cd] %%@",property];
            NSPredicate *predicate = [NSPredicate predicateWithFormat:mainString, string];
            [subPredicates addObject:predicate];
        }


    if ([searchString containsString:@" "] && subPredicates.count > 0) {
        NSString *mainString = [property stringByAppendingString:@" CONTAINS[cd] "];
        mainString = [mainString stringByAppendingString:@"' '"];

        NSPredicate *emptySpacePredicate = [NSPredicate predicateWithFormat:mainString, nil];

        [subPredicates addObject:emptySpacePredicate];
    }


    NSCompoundPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates];

    return predicate;
}

假设我们有一个带有name 属性的Contact 对象

NSPredicate *namePredicate = [self wordBasedPredicateForString:searchString withProperty: @"name"];

然后过滤数组:

NSArray *results = [contacts filteredArrayUsingPredicate:namePredicate];

当然,您可以为姓名、公司、地址等创建多个词基谓词,并像这样创建一个复合谓词:

orPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[namePredicate, addressPredicate, phonePredicate]];

希望它会有所帮助;)

【讨论】:

    【解决方案2】:

    你也可以试试这个解决方案

    我们来看看MyContact

    class MyContact: NSManagedObject {
    
        @NSManaged var contact_id: String // Primary key
        @NSManaged var firstname: String
        @NSManaged var lastname: String
    
        var fullName: String {
            return firstname + " " + lastname
        }
    
    }
    

    现在您的对象中有fullName 字符串。因此您可以轻松地触发谓词。没关系,您的searchString 匹配您的名字或姓氏。

    现在添加搜索逻辑:-

    var currentContacts : [MyContact] = []
    var contacts : [MyContact] = []
    

    您的 tableView 委托方法使用 currentContacts 数组和 contacts 数组只是保持所有联系。

    您可以根据搜索字符串过滤contacts 数组。

    currentContacts = contacts.filter { (element: MyContact) -> Bool in
        return element.fullName.localizedCaseInsensitiveContainsString(searchString)
    }
    tableView.reloadData()
    

    希望它会有所帮助;)

    【讨论】:

      最近更新 更多