UICollectionView insertItemsAtIndexPaths: lanza la excepción

UICollectionView: Lo estoy haciendo mal. Simplemente no sé cómo.

Mi configuración

Estoy ejecutando esto en un iPhone 4S con iOS 6.0.1.

Mi meta

Tengo una vista de tabla en la que una sección está dedicada a las imágenes:

Cuando el usuario toca la celda "Agregar imagen ...", se le pide que elija una imagen de su biblioteca de fotos o que tome una nueva con la cámara. Esa parte de la aplicación parece estar funcionando bien.

Cuando el usuario agrega una imagen por primera vez, la etiqueta "Sin imágenes" se eliminará de la segunda celda de la tabla y se agregará en su lugar una UICollectionView, creada mediante programación. Esa parte también parece estar funcionando bien.

Se supone que la vista de la colección muestra las imágenes que han agregado, y es aquí donde me encuentro con problemas. (Sé que voy a tener que saltar a través de algunos aros para lograr que la celda de la vista de la tabla se amplíe a medida que aumenta el número de imágenes. Todavía no estoy tan lejos).

Cuando intento insertar un elemento en la vista de colección, se produce una excepción. Más sobre eso más adelante.

Mi código

Tengo el UITableViewController a cargo de la vista de tabla que también actúa como delegado y fuente de datos de la vista de colección. Aquí está el código relevante (omití los bits del controlador que considero no relacionados con este problema, incluidas las líneas en métodos como-viewDidLoad. También he omitido la mayoría del código de adquisición de imágenes ya que no creo que sea relevante):

#define ATImageThumbnailMaxDimension 100

@interface ATAddEditActivityViewController ()
{
    UICollectionView* imageDisplayView;
    NSMutableArray* imageViews;
}

@property (weak, nonatomic) IBOutlet UITableViewCell *imageDisplayCell;
@property (weak, nonatomic) IBOutlet UILabel *noImagesLabel;
@end

@implementation ATAddEditActivityViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    UICollectionViewFlowLayout* flowLayout = [[UICollectionViewFlowLayout alloc] init];
    flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;

    imageDisplayView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, 290, 120) collectionViewLayout:flowLayout];  // The frame rect still needs tweaking
    imageDisplayView.delegate = self;
    imageDisplayView.dataSource = self;
    imageDisplayView.backgroundColor = [UIColor yellowColor];  // Just so I can see the actual extent of the view
    imageDisplayView.opaque = YES;
    [imageDisplayView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"Cell"];

    imageViews = [NSMutableArray array];
}

#pragma mark - UIImagePickerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    /* ...code defining imageToSave omitted... */

    [self addImage:imageToSave toCollectionView:imageDisplayView];


    [self dismissModalViewControllerAnimated:YES];
}

#pragma mark - UICollectionViewDelegate
- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

#pragma mark - UICollectionViewDatasource
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
    [[cell  contentView] addSubview:imageViews[indexPath.row]];
    return cell;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return [imageViews count];
}

#pragma mark - UICollectionViewDelegateFlowLayout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return ((UIImageView*)imageViews[indexPath.item]).bounds.size;
}

#pragma mark - Image Handling
- (void)addImage:(UIImage*)image toCollectionView:(UICollectionView*)cv
{
    if ([imageViews count] == 0)  {
        [self.noImagesLabel removeFromSuperview];
        [self.imageDisplayCell.contentView addSubview:cv];
    }

    UIImageView* imageView = [[UIImageView alloc] initWithImage:image];
    /* ...code that sets the bounds of the image view omitted... */

    [imageViews addObject:imageView];
    [cv insertItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:[imageViews count]-1 inSection:0]]];
    [cv reloadData];
}

@end

Para resumir:

La vista de colección está instanciada y configurada en la-viewDidLoad métodoEl método UIImagePickerDelegate que recibe las llamadas de imagen elegidas-addImage:toCollectionView... que crea una nueva vista de imagen para mantener la imagen y la agrega a la matriz de datos y la vista de colección. Esta es la línea que produce la excepción.Los métodos de fuente de datos UICollectionView se basan en la matriz imageViews.La excepción

Aplicación finalizada debido a la excepción no detectada 'NSInternalInconsistencyException', motivo: 'Actualización no válida: número no válido de elementos en la sección 0. El número de elementos contenidos en una sección existente después de la actualización (1) debe ser igual al número de elementos contenidos en esa sección antes de la actualización (1), más o menos el número de elementos insertados o eliminados de esa sección (1 insertado, 0 eliminado) y más o menos el número de elementos movidos dentro o fuera de esa sección (0 movido dentro, 0 movido afuera).'

Si analizo este derecho, lo que me está diciendo es que la vista de colección (¡completamente nueva!) Cree que se creó con un solo elemento. Por lo tanto, he añadido un registro a-addImage:toCollectionView Para probar esta teoría:

NSLog(@"%d", [cv numberOfItemsInSection:0]);

¡Con esa línea ahí, la excepción nunca se lanza! La llamada a-numberOfItemsInSection: debe forzar la vista de colección para consultar su fuente de datos y darse cuenta de que no tiene elementos. O algo. Estoy conjeturando aquí. Pero, bueno, lo que sea: la vista de colección aún no muestra ningún elemento en este momento, así que todavía estoy haciendo algo mal y no sé qué.

En conclusiónObtengo una excepción impar cuando intento agregar un elemento a una vista de colección recién acuñada e insertada ... excepto cuando llamo-numberOfItemsInSection: Antes de intentar la inserción.Incluso si logro superar la excepción con una solución alternativa sombreada, los elementos aún no aparecen en la vista de colección.

Lo siento por la novela de una pregunta. ¿Algunas ideas?

Respuestas a la pregunta(4)

Su respuesta a la pregunta