我在实现搜索功能时犯了一个错误。我打开了一个异步线程。但是当删除一个字符(电话号码的一个数字)时,应用程序会崩溃。
错误:
***由于未捕获的异常'NSGenericException'终止应用程序,原因:'*** Collection< __ NSArrayM:0x117d7320>在被列举时被突变。'
代码:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
//
self.isSearch = YES;
//remove the last search all the contacts
[self.resultArr removeAllObjects];
//
[self.rcs_SearchTableView reloadData];
//
dispatch_queue_t uploadQueue = dispatch_get_global_queue(0, 0);
dispatch_queue_t getMainQueue = dispatch_get_main_queue();
dispatch_async(uploadQueue, ^{
NSMutableArray *phoneArr = (NSMutableArray *)[self rcs_GetPhoneNumberFromeDatabaseWithPhone:searchText];
//
//NSLog(@"清空上次搜索的数据:%@", self.resultArr);
//NSLog(@"输入的关键字是---%@---%lu",searchText,(unsigned long)searchText.length);
if (0 == searchText.length || [searchText isEqualToString:@" "]) {
self.isSearch = NO;
//[self.rcs_SearchTableView reloadData];
[self.resultArr removeAllObjects];
}
//[self.rcs_SearchTableView reloadData];
if (0 != phoneArr.count) {
//
for (NSUInteger i = 0; i < phoneArr.count; i ++) {
RCSPhoneModel *flagPhoneModel = phoneArr[i];
for (NSUInteger i = 0; i < self.rcsRecentSearchDataSource.count; i ++) {
RCSContactModel *flagModel = self.rcsRecentSearchDataSource[i];
if ([flagPhoneModel.serverId isEqualToString:flagModel.serverId] || [flagPhoneModel.phone isEqualToString:flagModel.name]) {
//the same contact has multiple Numbers To prevent repeated add the same contacts
if (![self.resultArr containsObject:flagModel]) {
[self.resultArr addObject:flagModel];
continue;
}
}
}
}
}else{
//search contacts by name
for (NSInteger i = 0; i < self.rcsRecentSearchDataSource.count; i ++) {
RCSContactModel *model = self.rcsRecentSearchDataSource[i];
NSString *nameStr = model.name;
if (nameStr.length >= searchText.length) {
//search all the name
if ([nameStr containsString:searchText]) {
[self.resultArr addObject:model];
}
}
}
}
//
if (self.resultArr.count > 0) {
self.isSearch = YES;
//[self.rcs_SearchTableView reloadData];
}
//The phone contacts or local contact synchronized to the server
dispatch_async(getMainQueue, ^{
[self.rcs_SearchTableView reloadData];
});
});
}
答案 0 :(得分:1)
for
循环不应枚举任何可能在任何其他线程上发生变化或可能在该循环内发生变化的内容。您应该只枚举一个您确定在枚举时不会更改的对象(在另一个线程中,或在循环内部)。一种方法是仅使用数组的本地副本来枚举。
我无法看到你的for
循环中枚举的内容在循环中发生了什么变化,所以我猜想在其他一些线程的其他代码中,你正在改变self.rcsRecentSearchDataSource
或phoneArr
。这会导致枚举for
或self.rcsRecentSearchDataSource
的{{1}}循环崩溃,因为在枚举时不需要更改。
这真的需要在一个单独的线程上运行吗?
如果是这样,请使用数组的线程局部副本来枚举,而不是原始数组。这样你可以确定没有别的东西可以修改它,因为它不存在于任何其他范围内。
例如,有两个地方可以将代码更改为:
phoneArr
以及您可以更改为的地方:
NSArray *localSearchDataSource = [self.rcsRecentSearchDataSource copy];
for (NSUInteger i = 0; i < localSearchDataSource.count; i ++) {
答案 1 :(得分:0)
我得到了答案并且喜欢欠码: - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { // self.isSearch = YES; // if(0 == searchText.length || [searchText isEqualToString:@“”]){ self.isSearch = NO; // [self.resultArr removeAllObjects]; } //删除最后一次搜索所有联系人 [self.resultArr removeAllObjects]; // [self.rcs_SearchTableView reloadData]; // NSMutableArray * localSearchDataSource = [self.resultArr mutableCopy]; //创建一个对象数组以及原始数组 //根据输入访问数据的电话号码 NSArray * localPhoneArr = [[self rcs_GetPhoneNumberFromeDatabaseWithPhone:searchText] copy]; // // [self.rcs_SearchTableView reloadData]; if(0!= localPhoneArr.count){ //因为数据匹配数字需要更长时间,使用异步线程 dispatch_queue_t uploadQueue = dispatch_get_global_queue(0,0); dispatch_queue_t getMainQueue = dispatch_get_main_queue(); dispatch_async(uploadQueue,^ { // for(NSUInteger i = 0; i&lt; localPhoneArr.count; i ++){ RCSPhoneModel * flagPhoneModel = localPhoneArr [i]; for(NSUInteger i = 0; i&lt; self.rcsRecentSearchDataSource.count; i ++){ RCSContactModel * flagModel = self.rcsRecentSearchDataSource [i];
if ([flagPhoneModel.serverId isEqualToString:flagModel.serverId] || [flagPhoneModel.phone isEqualToString:flagModel.name]) {
//The same contact has multiple Numbers To prevent repeated add the same contacts
if (![localSearchDataSource containsObject:flagModel]) {
[localSearchDataSource addObject:flagModel];
}
}
}
}
//Add the search results to the search data source
dispatch_async(getMainQueue, ^{
[self.resultArr addObjectsFromArray:localSearchDataSource];
[self.rcs_SearchTableView reloadData];
});
});
}else{
//Search contacts by name
for (NSInteger i = 0; i < self.rcsRecentSearchDataSource.count; i ++) {
RCSContactModel *model = self.rcsRecentSearchDataSource[i];
NSString *nameStr = model.name;
if (nameStr.length >= searchText.length) {
//Search all name
if ([nameStr containsString:searchText]) {
[self.resultArr addObject:model];
}
}
}
}
//
if (self.resultArr.count > 0) {
self.isSearch = YES;
[self.rcs_SearchTableView reloadData];
}
}
我做了两个更改'NSMutableArray * localSearchDataSource = [self.resultArr mutableCopy];'和'NSArray * localPhoneArr = [[self rcs_GetPhoneNumberFromeDatabaseWithPhone:searchText] copy];'。并完成它。集合&lt; __ NSArrayM:0x117d7320&gt;在被列举时被突变。'