警告:UICollectionViewFlowLayoutcaching了索引path'abc'的帧不匹配
这是导致警告的代码:
private override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { let attributes = super.layoutAttributesForItemAtIndexPath(indexPath) let distance = CGRectGetMidX(attributes!.frame) - self.midX; var transform = CATransform3DIdentity; transform = CATransform3DTranslate(transform, -distance, 0, -self.width); attributes!.transform3D = CATransform3DIdentity; return attributes }
控制台还打印:
这可能是因为stream布局“xyz”正在修改由UICollectionViewFlowLayout返回的属性而不复制它们。
我如何解决这个警告?
这可能是因为stream布局“xyz”正在修改由UICollectionViewFlowLayout返回的属性而不复制它们
果然,这就是你正在做的事情:
private override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { let attributes = super.layoutAttributesForItemAtIndexPath(indexPath) let distance = CGRectGetMidX(attributes!.frame) - self.midX; var transform = CATransform3DIdentity; transform = CATransform3DTranslate(transform, -distance, 0, -self.width); attributes!.transform3D = CATransform3DIdentity; return attributes }
我希望如果你只是说:
let attributes = super.layoutAttributesForItemAtIndexPath(indexPath).copy() as! UICollectionViewLayoutAttributes
或类似,问题将消失。
除了上面的很好的答案。
我知道示例代码是用swift编写的,但我认为有Objective-C版本会有所帮助。
对于Objective-C,这将不起作用,因为复制function只做浅拷贝。 你将不得不这样做:
NSArray * original = [super layoutAttributesForElementsInRect:rect]; NSArray * attributes = [[NSArray alloc] initWithArray:original copyItems:YES];
为了便于阅读,我添加了一个临时variables。
当重写layoutAttributesForElementsInRect
时,我有这个问题。 遍历super.layoutAttributesForElementsInRect(rect)
数组中的每个元素并调用copy对我来说都不起作用,所以我最终回到了Foundation类并使用NSArray
的copyItems
:
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? { // unwrap super's attributes guard let superArray = super.layoutAttributesForElementsInRect(rect) else { return nil } // copy items guard let attributes = NSArray(array: superArray, copyItems: true) as? [UICollectionViewLayoutAttributes] else { return nil } // modify attributes return attributes }
添加到@Georgi的答案
必须符合<NSCopying>
,并将复制消息调用添加到layoutAttributesForItemAtIndexPath
UICollectionViewLayoutAttributes* attributes = [[super layoutAttributesForItemAtIndexPath:indexPath] copy];
这不是原来的问题的答案,但可以帮助layoutAttributesForElements(rect:CGRect)(Swift 3.0):
let safeAttributes = super.layoutAttributesForElements(in: rect)?.map { $0.copy() as! UICollectionViewLayoutAttributes } safeAttributes?.forEach { /* do something with attributes*/ }
更新了Swift 3的响应!
for func layoutAttributesForElements
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { guard let attributes = super.layoutAttributesForElements(in: rect) else { return nil } guard let attributesToReturn = attributes.map( { $0.copy() }) as? [UICollectionViewLayoutAttributes] else { return nil } return attributesToReturn }
for func layoutAttributesForItem
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { guard let currentItemAttributes = super.layoutAttributesForItem(at: indexPath)?.copy() as? UICollectionViewLayoutAttributes else { return nil } return currentItemAttributes }
如果你重写这两个函数,你必须调用复制两个函数!
好的编码!
我已经分类了UICollectionViewFlowLayout
。 里面layoutAttributesForElementsInRect()
我做了这个改变:
从…改变
guard let attributesForItem: UICollectionViewLayoutAttributes = self.layoutAttributesForItemAtIndexPath(indexPath) else { return }
改成
guard let attributesForItem = self.layoutAttributesForItemAtIndexPath(indexPath)?.copy() as? UICollectionViewLayoutAttributes else { return }