Предупреждение: UICollectionViewFlowLayout имеет кэшированное несоответствие фрейма для пути индекса '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
}
Консоль также печатает:
Это, вероятно, происходит, потому что макет потока "xyz" изменяет атрибуты, возвращенные UICollectionViewFlowLayout, не копируя их.
Как мне исправить это предупреждение?
7 ответов
Это, вероятно, происходит, потому что макет потока "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
или подобное, проблема исчезнет.
В дополнение к отличному ответу выше.
Я знаю, что пример кода написан на быстром, но я подумал, что полезно иметь версию Objective-C.
Для Objective-C это не будет работать, потому что функция копирования делает только поверхностное копирование. Вам придется сделать это:
NSArray * original = [super layoutAttributesForElementsInRect:rect];
NSArray * attributes = [[NSArray alloc] initWithArray:original copyItems:YES];
Я добавил временную переменную для удобства чтения.
У меня была эта проблема при переопределении layoutAttributesForElementsInRect
, Итерация по каждому элементу в super.layoutAttributesForElementsInRect(rect)
Массив и вызывающая копия не работали для меня, поэтому я остановился на классах Foundation и использовал NSArray
"s 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
}
Это не ответ на оригинальный вопрос, но может помочь для layoutAttributesForElements(в прямоугольнике: CGRect) (Swift 3.0):
let safeAttributes = super.layoutAttributesForElements(in: rect)?.map { $0.copy() as! UICollectionViewLayoutAttributes }
safeAttributes?.forEach { /* do something with attributes*/ }
Добавление к ответу @Georgi
<NSCopying>
должен соответствовать и добавить копию сообщения вызова к layoutAttributesForItemAtIndexPath
UICollectionViewLayoutAttributes* attributes = [[super layoutAttributesForItemAtIndexPath:indexPath] copy];
Обновленный ответ для Swift 3!
для макета funcAttributesForElements
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
}
для 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
}