2015-01-28 3 views
0

Я пытаюсь удалить ячейки из UICollectionView в for.. in циклах и каждый раз, когда я получаю NSRangeException. Я не могу понять, почему это происходит, потому что сначала я сортирую свой массив, а затем пытаюсь удалить. Таким образом, проблема заключается в том, что я сначала пытаюсь отправить запрос на сервер, и только если ответ будет успешным, мои ячейки 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]; 
    } 

} 

Для примера здесь я выбираю 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, то , , 1,0. И в этот момент мой @catch обрабатывает исключение и пытается удалить элемент с [smArray removeObjectAtIndex:(unsigned int)pathRow-1];, а затем я получаю NSRangeException и мое приложение рушится. Что я делаю неправильно?

ответ

0

Я решил свою проблему с this Ответ и немного изменил мой код. У меня есть NSRangeException, потому что я удалил свои UICollectionView предметов через петлю. Вместо этого я должен лучше использовать несколько удаление мгновенно, как это:

// Delete the items from the data source. 
        [self deleteItemsFromDataSourceAtIndexPaths:selectedItemsIndexPaths]; 

         // Now delete the items from the collection view. 
        [sortMediaCollection deleteItemsAtIndexPaths:selectedItemsIndexPaths]; 

Так что теперь мой код выглядит следующим образом:

Pass через петлю:

- (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 
    }]; 
    } 
} 

Надеюсь, это будет полезно для кого-то.

0

Я получал ту же ошибку, но обнаружил, что она связана с другим классом, имеющим зеркальную копию массива, и этот класс получает доступ к удаленному индексу.

Вы можете добавить точку останова исключения, чтобы увидеть, где именно происходит исключение. Полезно для дифференциации ошибок в вашем коде с ошибками, исходящими из SDK iOS: NSRangeException when deleting last UICollectionViewCell

Смежные вопросы