UICollectionView insertItemsAtIndexPaths: throws exception

UICollectionView: je suis en train de faire le mal. Je ne sais juste pas comment.

Ma Configuration

Je suis l'exécution de ce sur un iPhone 4S avec iOS 6.0.1.

Mon Objectif

J'ai une table dans laquelle une section est consacrée aux images: UICollectionView insertItemsAtIndexPaths: throws exception

Lorsque l'utilisateur appuie sur le "Ajouter une Image..." de la cellule, ils sont invités à choisir une image à partir de leur bibliothèque de photos ou de prendre un nouveau avec l'appareil photo. La partie de l'application semble fonctionner correctement.

Lorsque l'utilisateur ajoute une image, le "Pas d'Images" étiquette sera supprimé à partir de la deuxième cellule de tableau, et un UICollectionView, créée par programme, est ajoutée à sa place. La partie semble également fonctionner correctement.

L'affichage de la collection est censé afficher les images qu'ils ont ajouté, et c'est là où je suis en cours d'exécution dans le pétrin. (Je sais que je vais avoir à sauter à travers des cerceaux pour obtenir l'affichage de la table de la cellule pour l'agrandir comme le nombre d'images augmente. Je ne suis pas loin encore.)

Lorsque je tente d'insérer un élément dans la vue de collection, elle lève une exception. Plus sur cela plus tard.

Mon Code

J'ai la UITableViewController en charge de l'affichage de la table en agissant comme l'affichage de la collection du délégué et de la source de données. Voici le code (j'ai omis les bits du contrôleur que je considère comme étrangers à ce problème, y compris les lignes dans les méthodes comme -viewDidLoad. J'ai aussi omis, en plus de l'acquisition de l'image de code car je ne pense pas que c'est pertinent):

#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

Pour résumer:

  • L'affichage de la collection est instancié et configuré dans le -viewDidLoad méthode
  • La UIImagePickerDelegate méthode qui reçoit l'image choisie appels -addImage:toCollectionView
  • ...qui crée une nouvelle image vue de contenir l'image et l'ajoute à la source de données tableau et la vue de collection. C'est la ligne qui produit de l'exception.
  • La UICollectionView source de données méthodes reposent sur l'imageViews tableau.

L'Exception

Résiliation d'application en raison de uncaught exception 'NSInternalInconsistencyException', la raison: 'mise à jour incorrecte: non valides nombre d'éléments dans la section 0. Le nombre d'éléments contenus dans une section existante après la mise à jour (1) doit être égal au nombre d'éléments contenus dans cette section avant la mise à jour (1), plus ou moins le nombre d'articles insérés ou supprimés à partir de cette section (1 inséré, 0 supprimés) et plus ou moins le nombre d'éléments déplacés dans cette section (0 déplacé, 0).'

Si je suis d'analyse de ce droit, ce que c'est de me dire, c'est que le (nouveau!) vue de collection pense qu'il a été créé avec un seul élément. Donc, j'ai ajouté un journal à -addImage:toCollectionView pour tester cette théorie:

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

Avec cette ligne là, l'exception n'est jamais jeté! L'appel à -numberOfItemsInSection: devez forcer l'affichage de la collection de consulter sa source de données et réaliser qu'il n'a pas d'éléments. Ou quelque chose. Je suis conjecturing ici. Mais, bien, que ce soit: l'affichage de la collection n'est toujours pas d'affichage de tous les éléments à ce point, donc je suis encore en train de faire quelque chose de mal et je ne sais pas quoi.

En Conclusion

  1. J'obtiens une exception lorsque je tente d'ajouter un élément à un nouvellement frappées et inséré vue de collection...sauf quand je l'appelle -numberOfItemsInSection: avant de tenter d'insertion.
  2. Même si je parviens à obtenir au-delà de l'exception avec une louche de solution de contournement, les éléments encore, n'apparaissent pas dans l'affichage de la collection.

Désolé pour le roman d'une question. Des idées?

La seule chose que je peux suggérer, c'est de mettre un NSLog déclaration après [imageViews addObject:imageView]; et dans -numberOfItemsInSection. Qui va vous dire exactement si votre tableau est ce qu'il est censé être et si numberOfItemsInSection est appelé au bon moment.

OriginalL'auteur Ryan Ballantyne | 2012-11-15