2016-10-18 21 views
6

Śledziłem tę Custom Collection View Layout tutorial z raywenderlich.com używając Xcode 8 i szybka 3.UICollectionViewLayout nie działa zgodnie z oczekiwaniami

Kiedy wpadłem aplikację po wdrożeniu wszystkich metod wymaganych w tutorialu, mam następujący błąd:

'no UICollectionViewLayoutAttributes instance for -layoutAttributesForItemAtIndexPath: {length = 2, path = 0 - 11}'

Więc dodałem następujące metody w mojej klasie CollectionViewFlowLayout:

override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { 

    return self.cache[indexPath.row] 
} 

To jest prawie pracy z wyjątkiem tego som Komórki e są nakładane na istniejące komórki podczas przewijania w dół, a następnie znikają. Jeśli przewijam w górę, wszystko działa idealnie.

Nie rozumiem pełnej logiki tego kodu, ale wielokrotnie sprawdzałem i testowałem go i nie mogę zrozumieć, która część kodu wywołuje to zachowanie.

Każdy pomysł?

import UIKit 

/* The heights are declared as constants outside of the class so they can be easily referenced elsewhere */ 
struct UltravisualLayoutConstants { 
struct Cell { 
    /* The height of the non-featured cell */ 
    static let standardHeight: CGFloat = 100 
    /* The height of the first visible cell */ 
    static let featuredHeight: CGFloat = 280 
} 
} 
class UltravisualLayout: UICollectionViewLayout { 
// MARK: Properties and Variables 

/* The amount the user needs to scroll before the featured cell changes */ 
let dragOffset: CGFloat = 180.0 

var cache = [UICollectionViewLayoutAttributes]() 

/* Returns the item index of the currently featured cell */ 
var featuredItemIndex: Int { 
    get { 
     /* Use max to make sure the featureItemIndex is never < 0 */ 
     return max(0, Int(collectionView!.contentOffset.y/dragOffset)) 
    } 
} 

/* Returns a value between 0 and 1 that represents how close the next cell is to becoming the featured cell */ 
var nextItemPercentageOffset: CGFloat { 
    get { 
     return (collectionView!.contentOffset.y/dragOffset) - CGFloat(featuredItemIndex) 
    } 
} 

/* Returns the width of the collection view */ 
var width: CGFloat { 
    get { 
     return collectionView!.bounds.width 
    } 
} 

/* Returns the height of the collection view */ 
var height: CGFloat { 
    get { 
     return collectionView!.bounds.height 
    } 
} 

/* Returns the number of items in the collection view */ 
var numberOfItems: Int { 
    get { 
     return collectionView!.numberOfItems(inSection: 0) 
    } 
} 

// MARK: UICollectionViewLayout 

/* Return the size of all the content in the collection view */ 
override var collectionViewContentSize : CGSize { 

    let contentHeight = (CGFloat(numberOfItems) * dragOffset) + (height - dragOffset) 

    return CGSize(width: width, height: contentHeight) 
} 

override func prepare() { 


    let standardHeight = UltravisualLayoutConstants.Cell.standardHeight 

    let featuredHeight = UltravisualLayoutConstants.Cell.featuredHeight 

    var frame = CGRect.zero 

    var y:CGFloat = 0 

    for item in 0 ... (numberOfItems - 1) { 

     let indexPath = NSIndexPath(item: item, section: 0) 

     let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath as IndexPath) 

     attributes.zIndex = item 

     var height = standardHeight 

     if indexPath.item == featuredItemIndex { 

      let yOffset = standardHeight * nextItemPercentageOffset 

      y = self.collectionView!.contentOffset.y - yOffset 

      height = featuredHeight 


     } else if item == (featuredItemIndex + 1) && item != numberOfItems { 

      let maxY = y + standardHeight 

      height = standardHeight + max((featuredHeight - standardHeight) * nextItemPercentageOffset, 0) 

      y = maxY - height 
     } 

     frame = CGRect(x: 0, y: y, width: width, height: height) 

     attributes.frame = frame 

     cache.append(attributes) 

     y = frame.maxY 
    } 
} 

/* Return all attributes in the cache whose frame intersects with the rect passed to the method */ 

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { 

    var layoutAttributes = [UICollectionViewLayoutAttributes]() 

    for attributes in cache { 

     if attributes.frame.intersects(rect) { 

      layoutAttributes.append(attributes) 
     } 
    } 

    return layoutAttributes 
} 

override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { 

    return self.cache[indexPath.row] 
} 

/* Return true so that the layout is continuously invalidated as the user scrolls */ 
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { 

    return true 
} 
} 

Odpowiedz

0

Wystarczy dodać, że w super.viewDidLoad kontrolera widoku posiadania pogląd UICollection i obecnie działa zgodnie z oczekiwaniami.

To jest szybka naprawa i uważam, że istnieje lepszy sposób na rozwiązanie tego problemu, lepiej zarządzając funkcjami pobierania wstępnego z IOS10.

if #available(iOS 10.0, *) { 
    collectionView!.prefetchingEnabled = false 
} 
Powiązane problemy