2016-10-18 28 views
6

我跟着这个Custom Collection View Layout tutorial从raywenderlich.com使用Xcode中8,迅速3.UICollectionViewLayout未如预期

当我在执行本教程所要求的所有方法之后跑的应用程序的工作,我得到了以下错误:

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

所以我加入了以下方法进入我CollectionViewFlowLayout类:

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

    return self.cache[indexPath.row] 
} 

这几乎是除了SOM工作当向下滚动然后消失时,e细胞覆盖现有细胞。如果我向上滚动,一切都很完美。

我不明白这段代码的完整逻辑,但我已经多次检查和测试过,并且我不明白哪部分代码触发了这种行为。

有什么想法?

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 
} 
} 

回答

0

刚刚添加了在拥有UICollection视图的视图控制器的super.viewDidLoad中,它现在按预期工作。

这是一个快速修复,我相信有一个更合适的方法来解决这个更好地管理IOS10的预取功能。

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