我在实现搜索功能时犯了一个错误。我开了一个异步线程。但是当删除一个字符(电话号码的数字)时,应用程序会崩溃。
错误:
*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x117d7320> was mutated while being enumerated.'
代码:
- (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];
});
});
}
最佳答案
for
循环不应枚举任何可能在任何其他线程上更改或可能在该循环内更改的内容。您应该只枚举一个您确定在枚举时不会更改的对象(在另一个线程中,或在循环本身内)。一种方法是仅使用数组的本地副本进行枚举。
我看不到在你的 for
循环中枚举的任何东西在循环中发生了变化,所以我猜想在其他线程的一些其他代码中,你正在改变 self.rcsRecentSearchDataSource
或 phoneArr
。这会使枚举 self.rcsRecentSearchDataSource
或 phoneArr
的 for
循环崩溃,因为它需要在枚举时不改变。
这真的需要在单独的线程上运行吗?
如果是这样,请使用数组的线程本地副本来枚举,而不是原始数组。这样你就可以确定没有其他东西可以修改它,因为它不存在于任何其他范围内。
例如,您可以在两个地方更改代码:
NSArray *localSearchDataSource = [self.rcsRecentSearchDataSource copy];
for (NSUInteger i = 0; i < localSearchDataSource.count; i ++) {
还有一个地方你可以改成:
NSArray *localPhoneArr = [[self rcs_GetPhoneNumberFromeDatabaseWithPhone:searchText] copy];
for (NSUInteger i = 0; i < localPhoneArr .count; i ++) {
关于ios - *** 集合 <__NSArrayM : 0x117d7320> was mutated while being enumerated. ',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43083550/