2012-10-14 11 views
14

Korzystanie z iOS 6 i nowy UICollectionView Mam 2 UICollectionViews na UIViewController i za pomocą Storyboard pojawia się następujący błąd po kliknięciu na całym UICollectionView Nie jestem pewien, dlaczego tak się dzieje i Google zwraca 0 wyników dla tego błędu ...błąd potwierdzenia w - [UICollectionViewData numberOfItemsBeforeSection:]

2012-10-13 20:30:06.421 MyApp[768:907] Assertion failure in -[UICollectionViewData numberOfItemsBeforeSection:], /SourceCache/UIKit/UIKit-2372/UICollectionViewData.m:415
2012-10-13 20:30:06.427 MyApp[768:907] Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'request for number of items before section 2147483647 when there are only 1 sections in the collection view'

nie używam w ogóle Sekcje i mieć go ustawić tylko 1 odcinku:

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView 
{ 
    return 1; 
} 

Zdarza się (pojawia się losowo), gdy klikam na obszarze UICollectionView Mam kawałek kodu do usuwania elementu z UICollectionView:

[tilesArray removeObjectAtIndex:indexPath.row]; 
[self.tilesCollectionView reloadData];   
[resultsArray addObject:str]; 
[self.resultsCollectionView reloadData]; 

Oto jak macierze podłączone do UICollectionViews

-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 

    if(collectionView.tag == 2) 
     return [resultsArray count]; 
    else 
     return [tilesArray count]; 
} 
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 

    if(collectionView.tag == 2) 
    { 
     static NSString *cellIdentifier = @"ResultCell"; 
     ResultCell *cell = (ResultCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath]; 

     cell.mainImage.image = [UIImage imageNamed:currentArtContainer.tileMainImage]; 

     NSString *cellData = [resultsArray objectAtIndex:indexPath.row]; 
     [cell.titleLabel setText:cellData]; 

     return cell; 
    } 
    else 
    { 
     static NSString *cellIdentifier = @"TileCell"; 
     TileCell *cell = (TileCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath]; 

     cell.topImage.image = [UIImage imageNamed:currentArtContainer.tileTopImage]; 

     cell.mainImage.image = [UIImage imageNamed:currentArtContainer.tileMainImage]; 

     NSString *cellData = [tilesArray objectAtIndex:indexPath.row]; 
     [cell.titleLabel setText:cellData]; 

     return cell; 
    } 
} 

Pomóż mi rozwiązać ten problem. Nie wiem nawet, w jaki sposób mogę wychwycić wyjątek, ponieważ pochodzi on z kodu wewnętrznego UICollectionView. Również zapomniałem wspomnieć, że używam niestandardowego układu dla UICollectionView, ale nie wiem, czy jest to związane z tym problemem.

Jeszcze raz dziękuję za pomoc!

Edit: Dostaję wyjątek po wszystkie metody layout są nazywane ... Oto mój niestandardowy układ ... ja nadal nie wiem, jak go naprawić od wszystkich moich bloków try catch nIE pułapkę błędu ...

- (void)prepareLayout 
{ 
    NSLog(@"In prepareLayout."); 

    [super prepareLayout]; 
    _cellCount = [[self collectionView] numberOfItemsInSection:0]; 
} 

- (CGSize)collectionViewContentSize 
{ 
    NSLog(@"In collectionViewContentSize."); 
    @try { 

     CGSize csize = [self collectionView].frame.size; 
     NSLog(@"In here."); 
     return csize; 
    } 
    @catch(NSException *exception) 
    { 
     NSLog(@"collectionViewContentSize %@: %@",[exception name],[exception reason]); 
    } 

} 

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
    @try { 

    NSLog(@"In layoutAttributesForItemAtIndexPath. item %d", indexPath.row); 


    UICollectionViewLayoutAttributes* attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 

    attributes.size = CGSizeMake(ITEM_SIZE, ITEM_SIZE); 

    NSLog(@"firstRun %d", self.firstRun); 
    //NSLog(@"panStatus %@", self.panStatus); 

    if (self.firstRun == 0) { 
     CGFloat x = 0, y = 0; 
     CGFloat boundx = self.collectionView.frame.size.width * 0.70; // Use the whole canvas 
     CGFloat boundy = self.collectionView.frame.size.height * 0.70; // Use the whole canvas 
     while (x < 50 || x > boundx) x = arc4random() % (int)boundx + indexPath.item; 
     while (y < 50 || y > boundy) y = arc4random() % (int)boundy + indexPath.item; 

     NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; 
     if (self.positions) 
      dictionary = [self.positions mutableCopy]; 
     [dictionary setObject:[NSValue valueWithCGPoint:CGPointMake(x, y)] forKey:@(indexPath.item)]; 
     if (!self.positions) 
      self.positions = [[NSDictionary alloc] init]; 
     self.positions = dictionary; 

     attributes.center = CGPointMake(x, y); 
    } else if (self.firstRun > 0) { 
     CGPoint point = [[self.positions objectForKey:@(indexPath.item)] CGPointValue]; 
     attributes.center = CGPointMake(point.x, point.y); 
    } 

    NSLog(@"END layoutAttributesForItemAtIndexPath. item %d", indexPath.row); 
     return attributes; 

    } 
    @catch(NSException *exception) 
    { 
     NSLog(@"layoutAttributesForItemAtIndexPath %@: %@",[exception name],[exception reason]); 
    } 
} 

-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 
{ 
    @try { 

    NSLog(@"layoutAttributesForElementsInRect ..."); 

    NSMutableArray* attributes = [NSMutableArray array]; 
    for (NSInteger i=0 ; i < self.cellCount; i++) { 
     NSIndexPath* indexPath = [NSIndexPath indexPathForItem:i inSection:1]; 
     [attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]]; 
    } 
    NSLog(@"END layoutAttributesForElementsInRect ..."); 
     return attributes; 

    } 
    @catch(NSException *exception) 
    { 
     NSLog(@"layoutAttributesForElementsInRect %@: %@",[exception name],[exception reason]); 
    } 
} 
+0

Czy główny widok, którego używasz, używa protokołu UICollectionViewDataSource? Czy ustawiłeś viewController (lub cokolwiek innego) jako źródło danych dla UICollectionView? – Cashew

+0

Tak. Implementuje 2 protokoły: UICollectionViewDelegate i UICollectionViewDataSource. Ustawiłem go jako źródło danych, a także deleguję dla 2 UICollectionViews na nim. – user1744168

Odpowiedz

6

kluczem tutaj jest to liczba z błędem:

2147483647

jest to wartość liczbowa NSNotFound. Gdzieś w swoim kodzie robisz coś w rodzaju indexOfObject: względem tablicy i przekazujesz jej wynik do jednego z twoich widoków kolekcji lub metod układu jako indeks sekcji lub przedmiotu, co powoduje błąd. Nie dzieje się to w kodzie opublikowanym w pytaniu, ale mam nadzieję, że będziesz mógł go teraz znaleźć.

+1

Wygląda na to, że problem nadchodzi z powodu mojego niestandardowego układu ... – user1744168

4

Ja sam wpadłem na to stwierdzenie. Został uruchomiony, ponieważ ponownie załadowałem dane dotyczące kolekcji w przypadku zdarzenia dotykowego (przesunięcia).

Początkowe dotknięcie (początek) wywołało komunikat didHighlightItemAtIndexPath:, a następnie zmieniono dane kolekcji (poprzez przesunięcie), a następnie nie udało się uruchomić komunikatu didUnhighlightItemAtIndexPath: na dotknięciu (podnieś).

Ponieważ nie muszę podkreślić, roztwór do wdrożenia tej metody w moim kontrolera:

- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
    return NO; 
} 

Mam nadzieję, że pomaga nikomu uruchomiony do tego.

+1

Chciałem tylko powiedzieć, że problem polegał na ponownym wczytaniu danych kolekcji podczas długiego naciśnięcia przycisku. Usunięcie reloadData naprawiło mój problem. –

9

Miałem to miejsce, gdy uruchomiłem program reloadData z poziomu narzędzia do rozpoznawania gestów, ustawiając opóźnieniaTouchesBegan opóźnienia na pomoc w rozpoznawaniu gestów.

3

Nigdy nie ładuj ponownie danych UICOllectionView na metodzie wykonywanej przez program do rozpoznawania gestów.Zgodnie z tą zasadą całkowicie rozwiązano ten problem. Sugestia Daltsy'ego o dezaktywacji highligting w UICollectionView zapobiega także błędowi, ale także dezaktywuje wszystkie wiadomości delegata "didSelectItemAtIndexPath". Bądź ostrożny, ponieważ możesz skończyć z prawie bezużytecznym UICollectionView - tak jak zrobiłem to kilka minut temu.

5

Ten pracował dla mnie:

dispatch_async(dispatch_get_main_queue(), ^{ 
    [self.collectionView reloadData]; 
}); 
+0

Wszelkie zmiany GUI muszą być uruchamiane z głównego wątku. Zmieniając lub odświeżając UICollectionView z bloku, opóźnienia lub rozpoznawania gestów, musisz wysłać go do głównej kolejki (jak to opisano powyżej @ Hampden123). – ripegooseberry

0

Zamiast wyłączyć podświetlanie, odkryłem, że upewniając się, że nie ma komórki są podświetlone przed wywołaniem reloadData zapobiega „Wniosek o liczbie pozycji przed sekcją” błąd. Jest to metoda w postaci Xamarin lub lub.

Zapisz uchwyt do aktualnie wybranego elementu w danych modelu, wyczyść podświetlanie widoku kolekcji, obliczyć nowe NSIndexPath dla elementów, a następnie wywołać polecenie reloadData. Poprzednio wybrany element jest ponownie wybierany za pomocą uchwytu, aby znaleźć go za pomocą jego potencjalnie nowej właściwości NSIndexPath.

selectItemAtIndexPath:animated:scrollPosition: lub SelectItem w Xamarin.