EMRealtimeSearch.m 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. //
  2. // EMRealtimeSearch.m
  3. // DXStudio
  4. //
  5. // Created by XieYajie on 22/09/2017.
  6. // Copyright © 2017 dxstudio. All rights reserved.
  7. //
  8. #import "EMRealtimeSearch.h"
  9. static EMRealtimeSearch *defaultUtil = nil;
  10. @interface EMRealtimeSearch()
  11. @property (weak, nonatomic) id source;
  12. @property (nonatomic) SEL selector;
  13. @property (copy, nonatomic) RealtimeSearchResultsBlock resultBlock;
  14. /**
  15. * 当前搜索线程
  16. */
  17. @property (strong, nonatomic) NSThread *searchThread;
  18. /**
  19. * 搜索线程队列
  20. */
  21. @property (strong, nonatomic) dispatch_queue_t searchQueue;
  22. @end
  23. @implementation EMRealtimeSearch
  24. @synthesize source = _source;
  25. @synthesize selector = _selector;
  26. @synthesize resultBlock = _resultBlock;
  27. - (instancetype)init
  28. {
  29. self = [super init];
  30. if (self) {
  31. _asWholeSearch = YES;
  32. _searchQueue = dispatch_queue_create("cn.realtimeSearch.queue", NULL);
  33. }
  34. return self;
  35. }
  36. /**
  37. * 实时搜索单例实例化
  38. *
  39. * @return 实时搜索单例
  40. */
  41. + (instancetype)shared
  42. {
  43. static dispatch_once_t onceToken;
  44. dispatch_once(&onceToken, ^{
  45. defaultUtil = [[EMRealtimeSearch alloc] init];
  46. });
  47. return defaultUtil;
  48. }
  49. #pragma mark - private
  50. - (void)realtimeSearch:(NSString *)string
  51. {
  52. [self.searchThread cancel];
  53. //开启新线程
  54. self.searchThread = [[NSThread alloc] initWithTarget:self selector:@selector(searchBegin:) object:string];
  55. [self.searchThread start];
  56. }
  57. - (void)searchBegin:(NSString *)string
  58. {
  59. __weak typeof(self) weakSelf = self;
  60. dispatch_async(self.searchQueue, ^{
  61. if (string.length == 0) {
  62. weakSelf.resultBlock(weakSelf.source);
  63. }
  64. else{
  65. NSMutableArray *results = [NSMutableArray array];
  66. NSString *subStr = [string lowercaseString];
  67. for (id object in weakSelf.source) {
  68. NSString *tmpString = @"";
  69. if (weakSelf.selector) {
  70. if([object respondsToSelector:weakSelf.selector])
  71. {
  72. #pragma clang diagnostic push
  73. #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
  74. tmpString = [[object performSelector:weakSelf.selector] lowercaseString];
  75. #pragma clang diagnostic pop
  76. }
  77. }
  78. else if ([object isKindOfClass:[NSString class]])
  79. {
  80. tmpString = [object lowercaseString];
  81. }
  82. else{
  83. continue;
  84. }
  85. if([tmpString rangeOfString:subStr].location != NSNotFound)
  86. {
  87. [results addObject:object];
  88. }
  89. }
  90. weakSelf.resultBlock(results);
  91. }
  92. });
  93. }
  94. #pragma mark - public
  95. /**
  96. * 开始搜索,只需要调用一次,与[realtimeSearchStop]配套使用
  97. *
  98. * @param source 要搜索的数据源
  99. * @param selector 获取元素中要比较的字段的方法
  100. * @param resultBlock 回调方法,返回搜索结果
  101. */
  102. - (void)realtimeSearchWithSource:(id)source searchText:(NSString *)searchText collationStringSelector:(SEL)selector resultBlock:(RealtimeSearchResultsBlock)resultBlock
  103. {
  104. if (!source || [searchText length] == 0 || !resultBlock) {
  105. if (resultBlock) {
  106. resultBlock(nil);
  107. }
  108. return;
  109. }
  110. _source = source;
  111. _selector = selector;
  112. _resultBlock = resultBlock;
  113. [self realtimeSearch:searchText];
  114. }
  115. /**
  116. * 从fromString中搜索是否包含searchString
  117. *
  118. * @param searchString 要搜索的字串
  119. * @param fromString 从哪个字符串搜索
  120. *
  121. * @return 是否包含字串
  122. */
  123. - (BOOL)realtimeSearchString:(NSString *)searchString fromString:(NSString *)fromString
  124. {
  125. if (!searchString || !fromString || (fromString.length == 0 && searchString.length != 0)) {
  126. return NO;
  127. }
  128. if (searchString.length == 0) {
  129. return YES;
  130. }
  131. NSUInteger location = [[fromString lowercaseString] rangeOfString:[searchString lowercaseString]].location;
  132. return (location == NSNotFound ? NO : YES);
  133. }
  134. /**
  135. * 结束搜索,只需要调用一次,在[realtimeSearchBeginWithSource:]之后使用,主要用于释放资源
  136. */
  137. - (void)realtimeSearchStop
  138. {
  139. [self.searchThread cancel];
  140. }
  141. @end