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