UICollectionView insertItemsAtIndexPaths: zgłasza wyjątek

UICollectionView: Źle to robię. Po prostu nie wiem jak.

Moja konfiguracja

Używam tego na iPhone 4S z iOS 6.0.1.

Mój cel

Mam widok tabeli, w którym jedna sekcja poświęcona jest obrazom:

Gdy użytkownik dotknie komórki „Dodaj obraz ...”, zostanie poproszony o wybranie obrazu z biblioteki zdjęć lub zrobienie nowego z aparatem. Ta część aplikacji działa dobrze.

Gdy użytkownik po raz pierwszy doda obraz, etykieta „Brak obrazów” zostanie usunięta z drugiej komórki tabeli, a na jej miejsce zostanie dodany UICollectionView, utworzony programowo. Ta część również działa dobrze.

Widok kolekcji ma wyświetlać obrazy, które dodali, i to tutaj wpadam w kłopoty. (Wiem, że będę musiał przeskoczyć przez kilka obręczy, aby komórka widoku tabeli powiększyła się w miarę wzrostu liczby obrazów. Nie jestem jeszcze tak daleko).

Gdy próbuję wstawić element do widoku kolekcji, zgłasza wyjątek. Więcej na ten temat później.

Mój kod

Wcześniej uzyskałem UITableViewController odpowiedzialny za widok tabeli również działający jako delegat widoku kolekcji i źródło danych. Oto odpowiedni kod (pominąłem bity kontrolera, które uważam za niezwiązane z tym problemem, w tym linie w metodach takich jak-viewDidLoad. Pominąłem też większość kodu pozyskiwania obrazów, ponieważ nie sądzę, że jest to istotne):

#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

Podsumowując:

Widok kolekcji jest tworzony i konfigurowany w-viewDidLoad metodaMetoda UIImagePickerDelegate, która odbiera wybrane wywołania obrazu-addImage:toCollectionView... który tworzy nowy widok obrazu, aby zatrzymać obraz i dodaje go do tablicy źródeł danych i widoku kolekcji. To jest linia, która tworzy wyjątek.Metody źródła danych UICollectionView polegają na tablicy imageViews.Wyjątek

Aplikacja kończąca z powodu nie przechwyconego wyjątku „NSInternalInconsistencyException”, powód: „Niepoprawna aktualizacja: niepoprawna liczba elementów w sekcji 0. Liczba elementów zawartych w istniejącej sekcji po aktualizacji (1) musi być równa liczbie elementów zawartych w tej sekcji sekcja przed aktualizacją (1), plus lub minus liczba elementów wstawionych lub usuniętych z tej sekcji (1 włożona, 0 usunięta) oraz plus lub minus liczba elementów przeniesionych do lub z tej sekcji (0 przeniesionych, 0 przeniesionych na zewnątrz).'

Jeśli analizuję to dobrze, to mówi mi, że widok kolekcji (nowy!) Uważa, że ​​został utworzony za pomocą jednego elementu. Dodałem więc dziennik do-addImage:toCollectionView przetestować tę teorię:

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

Z tą linią wyjątek nigdy nie zostanie rzucony! Wezwanie do-numberOfItemsInSection: musi zmusić widok kolekcji do sprawdzenia źródła danych i uświadomienia sobie, że nie ma żadnych elementów. Lub coś. Przypuszczam tutaj. Ale cóż, cokolwiek: widok kolekcji nadal nie wyświetla żadnych elementów, więc nadal robię coś złego i nie wiem co.

Na zakończenieDostaję dziwny wyjątek, gdy próbuję dodać element do nowo pobranego i wstawionego widoku kolekcji ... chyba że zadzwonię-numberOfItemsInSection: przed próbą włożenia.Nawet jeśli uda mi się ominąć wyjątek z podejrzanym obejściem, elementy nadal nie są wyświetlane w widoku kolekcji.

Przepraszam za powieść na pytanie. Jakieś pomysły?

questionAnswers(4)

yourAnswerToTheQuestion