2016-02-14 12 views
7

Mam UICollectionView z niestandardowym UICollectionLayout. Wszystko działa dobrze, dopóki nie spróbuję wstawić wiersza ...NSInternalInconsistencyException ', powód:' brak UICollectionViewLayoutAttributes instancji dla -layoutAttributesForItemAtIndexPath, układ niestandardowy

Następnie pojawia się następujący błąd i nie mogę wymyślić, jak go rozwiązać.

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'no UICollectionViewLayoutAttributes instance for -layoutAttributesForItemAtIndexPath: <NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0}' 
*** First throw call stack: 
(
0 CoreFoundation      0x000000010915ae65 __exceptionPreprocess + 165 
1 libobjc.A.dylib      0x0000000108789deb objc_exception_throw + 48 
2 CoreFoundation      0x000000010915acca +[NSException raise:format:arguments:] + 106 
3 Foundation       0x000000010591a4de -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 198 
4 UIKit        0x00000001073e361c -[UICollectionViewData layoutAttributesForItemAtIndexPath:] + 627 
5 UIKit        0x00000001073a2859 __51-[UICollectionView _viewAnimationsForCurrentUpdate]_block_invoke1541 + 176 
6 UIKit        0x00000001073a02ed -[UICollectionView _viewAnimationsForCurrentUpdate] + 4524 
7 UIKit        0x00000001073a4a5c __62-[UICollectionView _updateWithItems:tentativelyForReordering:]_block_invoke1611 + 197 
8 UIKit        0x0000000106be01b8 +[UIView(Animation) performWithoutAnimation:] + 65 
9 UIKit        0x00000001073a3e07 -[UICollectionView _updateWithItems:tentativelyForReordering:] + 3241 
10 UIKit        0x000000010739eb98 -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:] + 15556 
11 UIKit        0x00000001073a5ee7 -[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:] + 415 
12 UIKit        0x00000001073a5d25 -[UICollectionView _performBatchUpdates:completion:invalidationContext:] + 74 
13 UIKit        0x00000001073a5cc8 -[UICollectionView performBatchUpdates:completion:] + 53 
14 Qanda        0x0000000103d9e0d9 _TFC5Qanda32HomeFeedCollectionViewController22redrawViewAfterNewDatafS0_FGSaCS_10QandaModel_T_ + 4105 
15 Qanda        0x0000000103dad5ca _TFFFC5Qanda32HomeFeedCollectionViewController9fetchDataFS0_FT_T_U_FTGSqGSaCS_10QandaModel__Sb_T_U0_FT_T_ + 1274 
16 Qanda        0x0000000103afc6b7 _TTRXFo__dT__XFdCb__dT__ + 39 
17 libdispatch.dylib     0x0000000109dd7e5d _dispatch_call_block_and_release + 12 
18 libdispatch.dylib     0x0000000109df849b _dispatch_client_callout + 8 
19 libdispatch.dylib     0x0000000109de02af _dispatch_main_queue_callback_4CF + 1738 
20 CoreFoundation      0x00000001090bad09 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9 
21 CoreFoundation      0x000000010907c2c9 __CFRunLoopRun + 2073 
22 CoreFoundation      0x000000010907b828 CFRunLoopRunSpecific + 488 
23 GraphicsServices     0x000000010c171ad2 GSEventRunModal + 161 
24 UIKit        0x0000000106b34610 UIApplicationMain + 171 
25 Qanda        0x0000000103bb537d main + 109 
26 libdyld.dylib      0x0000000109e2c92d start + 1 
) 
libc++abi.dylib: terminating with uncaught exception of type NSException 

Oto kod dla mojego układu:

var numberOfColumns: Int = 1 
let cellPadding: CGFloat = 10 
let buttonContainerHeight: CGFloat = 50 
let DEFAULT_HEIGHT: CGFloat = 80 

private var contentWidth: CGFloat = UIScreen.mainScreen().bounds.width 
private var totalContentHeight: CGFloat = 0.0 

// Delegate 
var delegate: HomeFeedCollectionViewLayoutDelegate? 


var cache = [UICollectionViewLayoutAttributes]() 


override func prepareLayout() { 

    // If cache is empty, calculate the layout 
    if cache.isEmpty { 
     // Set the size 
     let columnWidth = contentWidth/CGFloat(numberOfColumns) 
     var contentHeight: CGFloat = 0.0 
     var column = 0 
     let xOffset: CGFloat = 0 
     var yOffset: CGFloat = 0 
     var yOffsetArray = [CGFloat]() 

     // First check if sections actually exist 
     if collectionView!.numberOfSections() > 0 { 

      // Loop through items in section 
      for item in 0 ..< collectionView!.numberOfItemsInSection(0) { 

       let indexPath = NSIndexPath(forItem: item, inSection: 0) 
       let width = columnWidth - cellPadding * 2 

       let questionHeight = delegate?.collectionView(collectionView!, heightForQuestionAtIndexPath: indexPath, withWidth:width) 


       // Calculate frame 
       var height: CGFloat! 

       if questionHeight > 0 { 
        height = DEFAULT_HEIGHT + buttonContainerHeight + questionHeight! + 10 
       } 
       else { 
        height = contentWidth + buttonContainerHeight 
       } 


       if yOffsetArray.isEmpty { 
        log.debug("yOffsetArray is EMPTY") 
       } 
       else { 
        yOffset = yOffsetArray[item - 1] - cellPadding 
       } 

       yOffsetArray.append(height + yOffset) 


       let frame = CGRect(x: xOffset, y: yOffset, width: columnWidth, height: height) 
       let insetFrame = CGRectInset(frame, cellPadding, cellPadding) 

       // Create instance of UICollectionViewLayoutAttribute & set insetFrame 
       let attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath) 
       attributes.frame = insetFrame 
       cache.append(attributes) 

       // Make content height 
       contentHeight = contentHeight + (height - cellPadding) 

       column = column >= (numberOfColumns - 1) ? 0 : ++column 

      } 

      self.totalContentHeight = contentHeight 

     } 

    } 

} 


override func collectionViewContentSize() -> CGSize { 
    return CGSize(width: UIScreen.mainScreen().bounds.width, height: self.totalContentHeight + cellPadding) 
} 


override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? { 
    var layoutAttributes = [UICollectionViewLayoutAttributes]() 

    for attributes in cache { 
     if CGRectIntersectsRect(attributes.frame, rect) { 
      layoutAttributes.append(attributes) 
     } 
    } 
    return layoutAttributes 
} 

EDIT: Zwężenie korzeń błędu, wydaje się, że UICollectionViewLayoutAttributes zwrócone są uaktualniane tylko do prawidłowego nową wartość, jeśli CV jest ponownie ładowane jako pierwsze. Jeśli jednak to zrobię, aktualizacja wsadowa zgłasza błąd, mówiąc, że całkowita liczba wierszy AFTER powinna być równa poprzedniej plus liczba wstawiona ... co ma sens.

EDYTOWANIE 2: Teraz jestem zagubiony. Czy aktualizacja wsadowa próbuje pobrać układ z domyślnego układu, a nie z własnego układu?

layoutAttributesForElementsInRect = [<UICollectionViewLayoutAttributes: 0x7ffc1d8baf70> index path: (<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0}); frame = (10 10; 355 405); , <UICollectionViewLayoutAttributes: 0x7ffc1d8a5930> index path: (<NSIndexPath: 0xc000000000200016> {length = 2, path = 0 - 1}); frame = (10 425; 355 143.222); , <UICollectionViewLayoutAttributes: 0x7ffc1d837240> index path: (<NSIndexPath: 0xc000000000400016> {length = 2, path = 0 - 2}); frame = (10 578.222; 355 143.222); [...] <UICollectionViewLayoutAttributes: 0x7ffc1d8d02f0> index path: (<NSIndexPath: 0xc000000002600016> {length = 2, path = 0 - 19}); frame = (10 3229.44; 355 143.222); ] 

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'no UICollectionViewLayoutAttributes instance for -layoutAttributesForItemAtIndexPath: <NSIndexPath: 0xc000000000200016> {length = 2, path = 0 - 1}' 

Jak to jest możliwe?

Odpowiedz

9

Dla tych, którzy napotykają ten sam problem, odkryłem, że kiedy robisz

self.collectionView?.performBatchUpdates({() -> Void in 
     // add new items into collection 
     self.collectionView?.insertItemsAtIndexPaths(indexPaths) 

     }, completion: { (finished) -> Void in 
      // do insertion animations 
    }); 

layoutAttributesForElementsInRect metoda nie jest wywoływana i layoutAttributesForItemAtIndexPath nazywa zamiast.

Dlatego należy również zastąpić layoutAttributesForItemAtIndexPath w układzie niestandardowym tak:

override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { 

    // Logic that calculates the UICollectionViewLayoutAttributes of the item 
    // and returns the UICollectionViewLayoutAttributes 
    return self.singleItemLayout(indexPath) 
} 

EDIT: Także, jeśli pojawią się błysk, gdy metoda partia insertItemsAtIndexPaths na jego własne.

+0

Mam [podobny problem] (https://stackoverflow.com/q/46599911/6536841), czy możesz mi pomóc z tym? Nie mam własnego układu, ale mam podobny błąd. –

+0

@NikhilManapure: czy możesz umieścić swój kod gdzieś, aby móc go obejrzeć? Może po prostu opublikuj nowe pytanie na SO i przypnij link. – Benjamin

+0

Mam już zadane pytanie, to tutaj https://stackoverflow.com/q/46599911/6536841 –

Powiązane problemy