测试已测试 | ✓ |
Lang语言 | Obj-CObjective C |
许可证 | 自定义 |
发布最新发布 | 2016年6月 |
由 Ben Gordon、Andrew Parsons 维护。
IMQuickSearch 是一个用于快速过滤包含各种自定义 NSObject 类的多个 NSArrays 的工具。它可以处理任何值,并且不仅仅受到 NSString 的限制。如果您选择,可以通过 NSNumber 来过滤 NSObject。然而,由于它的主要目的是快速过滤对象,当您通过 NSString 进行过滤时,它执行包含搜索 - 搜索 "Bo" 返回 "Bob"、"Probowl" 和 "Bojangles"。
所有重要的类都位于顶级目录 Classes
中。您要将文件复制到您的项目中的是
IMQuickSearch.{h,m}
IMQuickSearchFilter.{h,m}
只需在任何希望使用 IMQuickSearch 的类中添加 #import "IMQuickSearch.h"
即可。
Cocoapods
pod 'IMQuickSearch'
首先,您需要确保您的 NSArrays 中已经填充了 NSObjects,并且可以随时使用。从这里,您将创建 IMQuickSearchFilter 对象,如下所示
// Create People
IMPerson *p1 = ({
IMPerson *p = [IMPerson new];
p.firstName = @"Bob";
p.LastName = @"Williams";
p;
});
IMPerson *p2 = ({
IMPerson *p = [IMPerson new];
p.firstName = @"Alice";
p.LastName = @"Johnson";
p;
});
// Create Animals
IMAnimal *a1 = ({
IMAnimal *a = [IMAnimal new];
a.name = @"Aligator";
a;
});
IMAnimal *a2 = ({
IMAnimal *a = [IMAnimal new];
a.name = @"Bison";
a;
});
// Create Filters
IMQuickSearchFilter *peopleFilter = [IMQuickSearchFilter filterWithSearchArray:@[p1, p2] keys:@[@"firstName",@"lastName"]];
IMQuickSearchFilter *animalFilter = [IMQuickSearchFilter filterWithSearchArray:@[a1, a2] keys:@[@"name"]];
这里我创建了两个过滤器,一个用于人的数组,一个用于动物的数组。keys 参数直接对应于每个数组内部的对象上的属性。例如,我有一个 Person 对象,具有 firstName
和 lastName
属性,因此我在第一个过滤器中添加了两个键。您不需要将所有属性添加到 keys 数组中;只需添加您想要过滤的属性即可。
接下来,您需要使用您创建的两个过滤器初始化 IMQuickSearch 主对象
self.QuickSearch = [[IMQuickSearch alloc] initWithFilters:@[peopleFilter,animalFilter]];
完成后,您就可以开始搜索了!
通过数组进行搜索非常简单。您只需调用一个方法
NSArray *filteredResults = [self.QuickSearch filteredObjectsWithValue:@"al"];
// filteredResults = @[p2,a1];
在这里,我通过值 @"al"
过滤了第一个示例中的两个数组,返回了一个包含 p2 和 a1 对象的combined数组。这是因为在第一个数组中 p2.firstName == @"Alice"
,在第二个数组中 a1.name == @"Aligator"
。两个数组中的其他对象与要过滤的值不匹配。
使用`NSString`进行过滤可能是最常见的使用场景,但您也可以使用其他类类型进行过滤。`NSString`过滤会运行属性的比较搜索,从而实现快速的字符串过滤。任何其他值都会在属性中运行精确匹配搜索。例如,如果您正在搜索带有值`@4
`的`NSNumber`属性,则只能返回匹配的属性,而不是值为`@40
`的属性。
异步搜索
主要的`filteredObjectsWithValue:`方法在主线程上同步搜索对象。但是,如果您的数据集相当大,您可能想将这项工作移动到后台线程,以免影响或冻结UI。您可以使用以下方法完成此操作
__block NSArray *results;
[self.QuickSearch asynchronouslyFilterObjectsWithValue:@"Hello" completion:^(NSArray *filteredResults)
{
if (filteredResults) {
results = filteredResults;
}
}];
附加信息
@""
`进行过滤将返回所有带有`NSString`属性的的对象动态修改过滤器
您还可以使用此方法动态添加/移除IMQuickSearchFilter对象
IMQuickSearchFilter *someFilter;
// Add
[self.QuickSearch addFilter:someFilter];
// Remove
[self.QuickSearch removeFilter:someFilter];
这个库很好,但确实有一些不足之处。以下是它们:
没有递归对象图搜索。
这基本上意味着,如果您有一个具有`Person`对象数组的`Family`对象,每个`Person`对象都有一个`firstName`属性 - 您无法根据具有像您正在搜索的firstName的人员过滤家族列表。它不会在对象图中查找键,只支持顶层对象的属性。但是数组对基本检查有效。如果您有一个`NSString`的`NSArray`,则会遍历数组,查看其中一个字符串是否匹配,然后返回`YES/NO`。
没有并行搜索。
目前,每个IMQuickSearchFilter都是顺序搜索的,然后在最后创建一个并集集。对于每个过滤器,完成键集的方式完全相同。理论上,并行执行一切可能会更快。理论上... 目前如果您查看multithreaded
分支,您可以看到我尝试这样做。快速的基准测试显示,顺序执行只需要并发执行的72%的时间。这是非常奇怪的。由于这个原因,它还不适用于生产使用,但我们仍然认为如果做得正确,这样做是有价值的。问题可能与管理并发而不是轻量级顺序方法更频繁、更重的实例化有关。
不能拯救世界。
不幸的是,如果出现严重情况,这个库不能拯救世界。尽管我们欢迎拉取请求。
在演示项目中对相同的`IMPerso n`和`IMAnimal`对象进行了一些基本测试后,它似乎会随着数据规模的增加而线性增长。对象数量增加10倍会导致速度降低10倍。以下是快速且混乱的结果(每个集合是1/2人,1/2动物)
iPhone 5C
200 objects - Avg. Runtime: 944661 ns (0.0009 s)
2000 objects - Avg. Runtime: 6899177 ns (0.0069 s)
20000 objects - Avg. Runtime: 79806582 ns (0.08 s)
现在,让我们测试后续搜索。这是使用相同的2000个对象数据集(1/2人,1/2动物)。因为我们正在保留最后一个搜索集,并且下一个搜索集包含在最后一个集合中,所以我们不需要每次都使用对象的主列表 - 只在上一个集合不会包含最新的搜索集时才使用。以下是这些基准测试。
Value: @"a"
2014-04-28 08:38:23.575 IMQuickSearch[27953:60b] Start
2014-04-28 08:38:23.621 IMQuickSearch[27953:60b] Stop
0.046s
Value: @"al"
2014-04-28 08:38:25.497 IMQuickSearch[27953:60b] Start
2014-04-28 08:38:25.533 IMQuickSearch[27953:60b] Stop
0.036s
Value: @"ali"
2014-04-28 08:38:26.645 IMQuickSearch[27953:60b] Start
2014-04-28 08:38:26.655 IMQuickSearch[27953:60b] Stop
0.010s
Value: @"alig"
2014-04-28 08:40:39.194 IMQuickSearch[27953:60b] Start
2014-04-28 08:40:39.196 IMQuickSearch[27953:60b] Stop
0.002s
运行,玩,并阅读演示项目以了解一切是如何工作的以及如何在自己的应用程序中使用它。
在Demo项目中包含了一些测试用例,库本身也经过测试,并与Travis-CI持续集成服务器进行了执行。
该仓库遵循标准MIT许可证。您可以在此处阅读许可证。