123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- //
- // EMRealtimeSearch.m
- // DXStudio
- //
- // Created by XieYajie on 22/09/2017.
- // Copyright © 2017 dxstudio. All rights reserved.
- //
- #import "EMRealtimeSearch.h"
- static EMRealtimeSearch *defaultUtil = nil;
- @interface EMRealtimeSearch()
- @property (weak, nonatomic) id source;
- @property (nonatomic) SEL selector;
- @property (copy, nonatomic) RealtimeSearchResultsBlock resultBlock;
- /**
- * 当前搜索线程
- */
- @property (strong, nonatomic) NSThread *searchThread;
- /**
- * 搜索线程队列
- */
- @property (strong, nonatomic) dispatch_queue_t searchQueue;
- @end
- @implementation EMRealtimeSearch
- @synthesize source = _source;
- @synthesize selector = _selector;
- @synthesize resultBlock = _resultBlock;
- - (instancetype)init
- {
- self = [super init];
- if (self) {
- _asWholeSearch = YES;
- _searchQueue = dispatch_queue_create("cn.realtimeSearch.queue", NULL);
- }
-
- return self;
- }
- /**
- * 实时搜索单例实例化
- *
- * @return 实时搜索单例
- */
- + (instancetype)shared
- {
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- defaultUtil = [[EMRealtimeSearch alloc] init];
- });
-
- return defaultUtil;
- }
- #pragma mark - private
- - (void)realtimeSearch:(NSString *)string
- {
- [self.searchThread cancel];
-
- //开启新线程
- self.searchThread = [[NSThread alloc] initWithTarget:self selector:@selector(searchBegin:) object:string];
- [self.searchThread start];
- }
- - (void)searchBegin:(NSString *)string
- {
- __weak typeof(self) weakSelf = self;
- dispatch_async(self.searchQueue, ^{
- if (string.length == 0) {
- weakSelf.resultBlock(weakSelf.source);
- }
- else{
- NSMutableArray *results = [NSMutableArray array];
- NSString *subStr = [string lowercaseString];
- for (id object in weakSelf.source) {
- NSString *tmpString = @"";
- if (weakSelf.selector) {
- if([object respondsToSelector:weakSelf.selector])
- {
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
- tmpString = [[object performSelector:weakSelf.selector] lowercaseString];
- #pragma clang diagnostic pop
-
- }
- }
- else if ([object isKindOfClass:[NSString class]])
- {
- tmpString = [object lowercaseString];
- }
- else{
- continue;
- }
-
- if([tmpString rangeOfString:subStr].location != NSNotFound)
- {
- [results addObject:object];
- }
- }
-
- weakSelf.resultBlock(results);
- }
- });
- }
- #pragma mark - public
- /**
- * 开始搜索,只需要调用一次,与[realtimeSearchStop]配套使用
- *
- * @param source 要搜索的数据源
- * @param selector 获取元素中要比较的字段的方法
- * @param resultBlock 回调方法,返回搜索结果
- */
- - (void)realtimeSearchWithSource:(id)source searchText:(NSString *)searchText collationStringSelector:(SEL)selector resultBlock:(RealtimeSearchResultsBlock)resultBlock
- {
- if (!source || [searchText length] == 0 || !resultBlock) {
- if (resultBlock) {
- resultBlock(nil);
- }
- return;
- }
-
- _source = source;
- _selector = selector;
- _resultBlock = resultBlock;
- [self realtimeSearch:searchText];
- }
- /**
- * 从fromString中搜索是否包含searchString
- *
- * @param searchString 要搜索的字串
- * @param fromString 从哪个字符串搜索
- *
- * @return 是否包含字串
- */
- - (BOOL)realtimeSearchString:(NSString *)searchString fromString:(NSString *)fromString
- {
- if (!searchString || !fromString || (fromString.length == 0 && searchString.length != 0)) {
- return NO;
- }
- if (searchString.length == 0) {
- return YES;
- }
-
- NSUInteger location = [[fromString lowercaseString] rangeOfString:[searchString lowercaseString]].location;
- return (location == NSNotFound ? NO : YES);
- }
- /**
- * 结束搜索,只需要调用一次,在[realtimeSearchBeginWithSource:]之后使用,主要用于释放资源
- */
- - (void)realtimeSearchStop
- {
- [self.searchThread cancel];
- }
- @end
|