删除 UICollectionView 单元格时出现 NSRangeException
NSRangeException while deleting UICollectionView cells
我试图从 for.. in
循环中的 UICollectionView
中删除单元格,每次我得到 NSRangeException
。我不明白为什么会这样,因为首先我对数组进行排序,然后尝试删除。所以问题是我首先尝试向服务器发送请求,只有当响应成功时,我的 UICollectionView
单元格和数组元素才会被删除。这是我的代码:
通过循环传递元素:
- (IBAction)deletePictures:(id)sender {
int i = 0;
if (selectedPhotosURL.count>0){
loadCount = (int)selectedPhotosURL.count;
//sorting an array (it works fine)
NSArray *indexPaths = sortMediaCollection.indexPathsForSelectedItems;
NSMutableArray *pathes = [NSMutableArray arrayWithArray:indexPaths];
NSSortDescriptor *highestToLowest = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:NO];
[pathes sortUsingDescriptors:[NSArray arrayWithObject:highestToLowest]];
[selecedCellsArray sortUsingComparator:^NSComparisonResult(NSString *str1, NSString *str2) {
return [str2 compare:str1 options:(NSNumericSearch)];
}];
NSLog(@"selectedCElls %@",selecedCellsArray);
for(NSIndexPath *indexPath in pathes) {
NSLog(@"indexPath in pathes is %ld",(long)indexPath.row);
AVMSMCell *cell = (AVMSMCell *)[sortMediaCollection cellForItemAtIndexPath:indexPath];
AVMDataStore *oneItem = [smArray objectAtIndex:indexPath.row];
NSString *contentId = oneItem.fileId;
if (i<selectedPhotosURL.count){
NSLog(@"indexPath second loop is %ld",(long)indexPath.row);
[self deleteUserPhotos:contentId : indexPath.row : cell]; // send request to the server it's ok too.
i++;
}
}
} else {
[self selectAtLeastOneFirst];
}
}
例如,这里我 select 6 个单元格和我的数组按正确的顺序从上到下排序 (5,4,3,2,1,0)。然后我按照这个顺序在方法中传递这个元素。
请求发送方式:
-(void)deleteUserPhotos : (NSString *)contentId : (NSInteger )pathRow : (AVMSMCell *) cell{
NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)pathRow];
if (([selecedCellsArray containsObject:[NSString stringWithFormat:@"%@",rowNsNum]]) )
{
cell.selectedBG.backgroundColor = DANGER;
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSString *token = [defaults objectForKey:@"token"];
NSString *header = [NSString stringWithFormat:@"Bearer %@",token];
NSDictionary *params = @{@"lang": @"en",@"content_id":contentId,@"project_id":[defaults objectForKey:@"project_id"]};
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager.requestSerializer setValue:header forHTTPHeaderField:@"Authorization"];
[manager POST:@"http://example.com/api/project/delete-content" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSLog(@"JSON: %@", responseObject);
if ([[responseObject objectForKey:@"result"] isEqualToString:@"success"]){
@try{
NSLog(@"pathRow in TRY %ld",(long)pathRow); // HERE I get wrong number after two or three elements already passed
[smArray removeObjectAtIndex:(unsigned int)pathRow];
[selecedCellsArray removeObject:[NSString stringWithFormat:@"%ld",(long)pathRow]];
cell.selectedBG.hidden = YES;
[sortMediaCollection reloadSections:[NSIndexSet indexSetWithIndex:0]];
loadCount--;
}
} @catch (NSException *e){
NSLog(@"something is bad %@",e);
[SVProgressHUD dismiss];
if (smArray.count<pathRow-1){
[smArray removeObjectAtIndex:(unsigned int)pathRow-1];
}
} @finally {
cell.selectedBG.hidden = YES;
[sortMediaCollection reloadSections:[NSIndexSet indexSetWithIndex:0]];
}
} else {
NSLog(@"can't delete photo!");
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSLog(@"Error: %@", error);
errorEndSpinner
}];
}
}
所以在上面的方法中,我在两个或三个元素已经通过后得到了错误的元素编号,即第一个元素是 5,然后是 4,然后是 2,3,1,0。
此时我的 @catch
处理异常并尝试使用 [smArray removeObjectAtIndex:(unsigned int)pathRow-1];
删除元素然后我得到 NSRangeException
和我的应用程序崩溃。我做错了什么?
我用 this 答案解决了我的问题,并对我的代码做了一点修改。
我有一个 NSRangeException
因为我通过循环删除了我的 UICollectionView
项目。相反,我应该像这样立即使用多次删除:
// Delete the items from the data source.
[self deleteItemsFromDataSourceAtIndexPaths:selectedItemsIndexPaths];
// Now delete the items from the collection view.
[sortMediaCollection deleteItemsAtIndexPaths:selectedItemsIndexPaths];
所以现在我的代码如下所示:
通过循环:
- (IBAction)deletePictures:(id)sender {
int i = 0;
if (selectedPhotosURL.count>0){
[SVProgressHUD showWithStatus:@"Deleting" maskType:SVProgressHUDMaskTypeBlack];
loadCount = (int)selectedPhotosURL.count;
NSArray *indexPaths = sortMediaCollection.indexPathsForSelectedItems;
NSMutableArray *pathes = [NSMutableArray arrayWithArray:indexPaths];
NSSortDescriptor *highestToLowest = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:NO];
[pathes sortUsingDescriptors:[NSArray arrayWithObject:highestToLowest]];
[selecedCellsArray sortUsingComparator:^NSComparisonResult(NSString *str1, NSString *str2) {
return [str2 compare:str1 options:(NSNumericSearch)];
}];
for(NSIndexPath *indexPath in pathes) {
AVMSMCell *cell = (AVMSMCell *)[sortMediaCollection cellForItemAtIndexPath:indexPath];
AVMDataStore *oneItem = [smArray objectAtIndex:indexPath.row];
NSString *contentId = oneItem.fileId;
if (i<selectedPhotosURL.count){
[self deleteUserPhotos:contentId : indexPath.row : cell pathes:pathes]; //pass array with pathes into 'deleteUserPhotos'
i++;
}
}
} else {
[self selectAtLeastOneFirst];
}
}
主要方法:
-(void)deleteItemsFromDataSourceAtIndexPaths:(NSArray *)itemPaths {
NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet];
for (NSIndexPath *itemPath in itemPaths) {
[indexSet addIndex:itemPath.row];
}
[smArray removeObjectsAtIndexes:indexSet];
}
-(void)deleteUserPhotos : (NSString *)contentId : (NSInteger )pathRow : (AVMSMCell *) cell pathes:(NSMutableArray*)selectedItemsIndexPaths{
NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)pathRow];
if (([selecedCellsArray containsObject:[NSString stringWithFormat:@"%@",rowNsNum]]))
{
cell.selectedBG.backgroundColor = DANGER;
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSString *token = [defaults objectForKey:@"token"];
NSString *header = [NSString stringWithFormat:@"Bearer %@",token];
NSDictionary *params = @{@"lang": @"en",@"content_id":contentId,@"project_id":[defaults objectForKey:@"project_id"]};
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager.requestSerializer setValue:header forHTTPHeaderField:@"Authorization"];
[manager POST:@"http://example.com/api/project/delete-content" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSLog(@"JSON: %@", responseObject);
if ([[responseObject objectForKey:@"result"] isEqualToString:@"success"]){
@try{
[selecedCellsArray removeObject:[NSString stringWithFormat:@"%ld",(long)pathRow]];
loadCount--;
if (loadCount==0){ //only there remove items from collectionview
// Delete the items from the data source.
[self deleteItemsFromDataSourceAtIndexPaths:selectedItemsIndexPaths];
// Now delete the items from the collection view.
[sortMediaCollection deleteItemsAtIndexPaths:selectedItemsIndexPaths];
[selectedPhotosURL removeAllObjects];
}
} @catch (NSException *e){
NSLog(@"something is bad %@",e);
[SVProgressHUD dismiss];
if (smArray.count<pathRow-1){
[smArray removeObjectAtIndex:(unsigned int)pathRow-1];
}
} @finally {
cell.selectedBG.hidden = YES;
[sortMediaCollection reloadSections:[NSIndexSet indexSetWithIndex:0]];
}
} else {
NSLog(@"can't delete photo!");
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSLog(@"Error: %@", error);
errorEndSpinner
}];
}
}
希望这对某些人有所帮助。
我遇到了同样的错误,但发现它与具有数组镜像副本的不同 class 以及 class 访问已删除的索引有关。
您可以添加异常断点以准确查看异常的来源。有助于区分代码中的错误和来自 iOS SDK 的错误:
我试图从 for.. in
循环中的 UICollectionView
中删除单元格,每次我得到 NSRangeException
。我不明白为什么会这样,因为首先我对数组进行排序,然后尝试删除。所以问题是我首先尝试向服务器发送请求,只有当响应成功时,我的 UICollectionView
单元格和数组元素才会被删除。这是我的代码:
通过循环传递元素:
- (IBAction)deletePictures:(id)sender {
int i = 0;
if (selectedPhotosURL.count>0){
loadCount = (int)selectedPhotosURL.count;
//sorting an array (it works fine)
NSArray *indexPaths = sortMediaCollection.indexPathsForSelectedItems;
NSMutableArray *pathes = [NSMutableArray arrayWithArray:indexPaths];
NSSortDescriptor *highestToLowest = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:NO];
[pathes sortUsingDescriptors:[NSArray arrayWithObject:highestToLowest]];
[selecedCellsArray sortUsingComparator:^NSComparisonResult(NSString *str1, NSString *str2) {
return [str2 compare:str1 options:(NSNumericSearch)];
}];
NSLog(@"selectedCElls %@",selecedCellsArray);
for(NSIndexPath *indexPath in pathes) {
NSLog(@"indexPath in pathes is %ld",(long)indexPath.row);
AVMSMCell *cell = (AVMSMCell *)[sortMediaCollection cellForItemAtIndexPath:indexPath];
AVMDataStore *oneItem = [smArray objectAtIndex:indexPath.row];
NSString *contentId = oneItem.fileId;
if (i<selectedPhotosURL.count){
NSLog(@"indexPath second loop is %ld",(long)indexPath.row);
[self deleteUserPhotos:contentId : indexPath.row : cell]; // send request to the server it's ok too.
i++;
}
}
} else {
[self selectAtLeastOneFirst];
}
}
例如,这里我 select 6 个单元格和我的数组按正确的顺序从上到下排序 (5,4,3,2,1,0)。然后我按照这个顺序在方法中传递这个元素。
请求发送方式:
-(void)deleteUserPhotos : (NSString *)contentId : (NSInteger )pathRow : (AVMSMCell *) cell{
NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)pathRow];
if (([selecedCellsArray containsObject:[NSString stringWithFormat:@"%@",rowNsNum]]) )
{
cell.selectedBG.backgroundColor = DANGER;
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSString *token = [defaults objectForKey:@"token"];
NSString *header = [NSString stringWithFormat:@"Bearer %@",token];
NSDictionary *params = @{@"lang": @"en",@"content_id":contentId,@"project_id":[defaults objectForKey:@"project_id"]};
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager.requestSerializer setValue:header forHTTPHeaderField:@"Authorization"];
[manager POST:@"http://example.com/api/project/delete-content" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSLog(@"JSON: %@", responseObject);
if ([[responseObject objectForKey:@"result"] isEqualToString:@"success"]){
@try{
NSLog(@"pathRow in TRY %ld",(long)pathRow); // HERE I get wrong number after two or three elements already passed
[smArray removeObjectAtIndex:(unsigned int)pathRow];
[selecedCellsArray removeObject:[NSString stringWithFormat:@"%ld",(long)pathRow]];
cell.selectedBG.hidden = YES;
[sortMediaCollection reloadSections:[NSIndexSet indexSetWithIndex:0]];
loadCount--;
}
} @catch (NSException *e){
NSLog(@"something is bad %@",e);
[SVProgressHUD dismiss];
if (smArray.count<pathRow-1){
[smArray removeObjectAtIndex:(unsigned int)pathRow-1];
}
} @finally {
cell.selectedBG.hidden = YES;
[sortMediaCollection reloadSections:[NSIndexSet indexSetWithIndex:0]];
}
} else {
NSLog(@"can't delete photo!");
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSLog(@"Error: %@", error);
errorEndSpinner
}];
}
}
所以在上面的方法中,我在两个或三个元素已经通过后得到了错误的元素编号,即第一个元素是 5,然后是 4,然后是 2,3,1,0。
此时我的 @catch
处理异常并尝试使用 [smArray removeObjectAtIndex:(unsigned int)pathRow-1];
删除元素然后我得到 NSRangeException
和我的应用程序崩溃。我做错了什么?
我用 this 答案解决了我的问题,并对我的代码做了一点修改。
我有一个 NSRangeException
因为我通过循环删除了我的 UICollectionView
项目。相反,我应该像这样立即使用多次删除:
// Delete the items from the data source.
[self deleteItemsFromDataSourceAtIndexPaths:selectedItemsIndexPaths];
// Now delete the items from the collection view.
[sortMediaCollection deleteItemsAtIndexPaths:selectedItemsIndexPaths];
所以现在我的代码如下所示:
通过循环:
- (IBAction)deletePictures:(id)sender {
int i = 0;
if (selectedPhotosURL.count>0){
[SVProgressHUD showWithStatus:@"Deleting" maskType:SVProgressHUDMaskTypeBlack];
loadCount = (int)selectedPhotosURL.count;
NSArray *indexPaths = sortMediaCollection.indexPathsForSelectedItems;
NSMutableArray *pathes = [NSMutableArray arrayWithArray:indexPaths];
NSSortDescriptor *highestToLowest = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:NO];
[pathes sortUsingDescriptors:[NSArray arrayWithObject:highestToLowest]];
[selecedCellsArray sortUsingComparator:^NSComparisonResult(NSString *str1, NSString *str2) {
return [str2 compare:str1 options:(NSNumericSearch)];
}];
for(NSIndexPath *indexPath in pathes) {
AVMSMCell *cell = (AVMSMCell *)[sortMediaCollection cellForItemAtIndexPath:indexPath];
AVMDataStore *oneItem = [smArray objectAtIndex:indexPath.row];
NSString *contentId = oneItem.fileId;
if (i<selectedPhotosURL.count){
[self deleteUserPhotos:contentId : indexPath.row : cell pathes:pathes]; //pass array with pathes into 'deleteUserPhotos'
i++;
}
}
} else {
[self selectAtLeastOneFirst];
}
}
主要方法:
-(void)deleteItemsFromDataSourceAtIndexPaths:(NSArray *)itemPaths {
NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet];
for (NSIndexPath *itemPath in itemPaths) {
[indexSet addIndex:itemPath.row];
}
[smArray removeObjectsAtIndexes:indexSet];
}
-(void)deleteUserPhotos : (NSString *)contentId : (NSInteger )pathRow : (AVMSMCell *) cell pathes:(NSMutableArray*)selectedItemsIndexPaths{
NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)pathRow];
if (([selecedCellsArray containsObject:[NSString stringWithFormat:@"%@",rowNsNum]]))
{
cell.selectedBG.backgroundColor = DANGER;
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSString *token = [defaults objectForKey:@"token"];
NSString *header = [NSString stringWithFormat:@"Bearer %@",token];
NSDictionary *params = @{@"lang": @"en",@"content_id":contentId,@"project_id":[defaults objectForKey:@"project_id"]};
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager.requestSerializer setValue:header forHTTPHeaderField:@"Authorization"];
[manager POST:@"http://example.com/api/project/delete-content" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSLog(@"JSON: %@", responseObject);
if ([[responseObject objectForKey:@"result"] isEqualToString:@"success"]){
@try{
[selecedCellsArray removeObject:[NSString stringWithFormat:@"%ld",(long)pathRow]];
loadCount--;
if (loadCount==0){ //only there remove items from collectionview
// Delete the items from the data source.
[self deleteItemsFromDataSourceAtIndexPaths:selectedItemsIndexPaths];
// Now delete the items from the collection view.
[sortMediaCollection deleteItemsAtIndexPaths:selectedItemsIndexPaths];
[selectedPhotosURL removeAllObjects];
}
} @catch (NSException *e){
NSLog(@"something is bad %@",e);
[SVProgressHUD dismiss];
if (smArray.count<pathRow-1){
[smArray removeObjectAtIndex:(unsigned int)pathRow-1];
}
} @finally {
cell.selectedBG.hidden = YES;
[sortMediaCollection reloadSections:[NSIndexSet indexSetWithIndex:0]];
}
} else {
NSLog(@"can't delete photo!");
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSLog(@"Error: %@", error);
errorEndSpinner
}];
}
}
希望这对某些人有所帮助。
我遇到了同样的错误,但发现它与具有数组镜像副本的不同 class 以及 class 访问已删除的索引有关。
您可以添加异常断点以准确查看异常的来源。有助于区分代码中的错误和来自 iOS SDK 的错误: