C'est le code à l'origine de l'avertissement:
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
}
La console imprime également:
Cela est probablement dû au fait que la présentation de flux "xyz" modifie les attributs renvoyés par UICollectionViewFlowLayout sans les copier.
Comment puis-je résoudre cet avertissement?
Cela est probablement dû au fait que la présentation de flux "xyz" modifie les attributs renvoyés par UICollectionViewFlowLayout sans les copier
Et bien sûr, c'est ce que vous faites:
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
}
J'espère que si vous dites simplement:
let attributes =
super.layoutAttributesForItemAtIndexPath(indexPath).copy()
as! UICollectionViewLayoutAttributes
ou similaire, le problème disparaîtra.
En plus de la bonne réponse ci-dessus.
Je sais que l’exemple de code est écrit en Swift, mais j’ai pensé qu’il pourrait être utile d’avoir la version Objective-C.
Pour Objective-C, cela ne fonctionnera pas, car la fonction de copie effectue uniquement une copie superficielle. Vous devrez faire ceci:
NSArray * original = [super layoutAttributesForElementsInRect:rect];
NSArray * attributes = [[NSArray alloc] initWithArray:original copyItems:YES];
J'ai ajouté une variable temporaire pour la lisibilité.
J'ai eu ce problème en surchargeant layoutAttributesForElementsInRect
. Itérer sur chaque élément du tableau super.layoutAttributesForElementsInRect(rect)
et la copie appelante ne fonctionnant pas pour moi, je me suis donc retourné vers les classes Foundation et j'ai utilisé 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
}
Ce n'est pas la réponse à la question initiale, mais peut aider pour layoutAttributesForElements (in rect: CGRect) (Swift 3.0):
let safeAttributes = super.layoutAttributesForElements(in: rect)?.map { $0.copy() as! UICollectionViewLayoutAttributes }
safeAttributes?.forEach { /* do something with attributes*/ }
Ajout à @Georgi answer
<NSCopying>
doit être conforme et ajouter un appel de message de copie à layoutAttributesForItemAtIndexPath
UICollectionViewLayoutAttributes* attributes = [[super layoutAttributesForItemAtIndexPath:indexPath] copy];
Réponse mise à jour pour Swift 3!
pour 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
}
pour func layoutAttributesForItem
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
guard let currentItemAttributes = super.layoutAttributesForItem(at: indexPath)?.copy() as? UICollectionViewLayoutAttributes else {
return nil
}
return currentItemAttributes
}
Si vous annulez les deux fonctions, vous devez appeler la copie pour les deux
Bon codage!
J'ai sous-classé UICollectionViewFlowLayout
. Dans layoutAttributesForElementsInRect()
j'ai fait ce changement:
changer de
guard let attributesForItem: UICollectionViewLayoutAttributes = self.layoutAttributesForItemAtIndexPath(indexPath) else {
return
}
changer à
guard let attributesForItem = self.layoutAttributesForItemAtIndexPath(indexPath)?.copy() as? UICollectionViewLayoutAttributes else {
return
}