0

UICollectionViewループ内からセルを削除しようとしてfor.. inいますが、取得するたびに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
    }];
    }
}

したがって、上記の方法では、2つまたは3つの要素がすでに渡された後、間違った要素番号を取得します。つまり、最初の要素は5、次に4、次に2、3、1、0です。そして、この時点で例外を処理し、要素を削除しようとすると、アプリがクラッシュします。私は何を間違っていますか?@catch[smArray removeObjectAtIndex:(unsigned int)pathRow-1];NSRangeException

4

2 に答える 2

0

この回答で問題を解決し、コードを少し修正しました。ループを介してアイテム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
    }];
  }
}

これが誰かに役立つことを願っています。

于 2015-01-29T05:53:51.033 に答える
0

同じエラーが発生していましたが、配列のミラー化されたコピーを持つ別のクラスと、そのクラスが削除されたインデックスにアクセスすることに関係していることがわかりました。

例外ブレークポイントを追加して、例外の発生元を正確に確認できます。コード内のエラーと iOS SDK からのエラーを区別するのに役立ちます:最後の UICollectionViewCell を削除するときの NSRangeException

于 2016-03-26T22:40:34.580 に答える