カスタム UICollectionViewLayout サブクラスがあります。prepareLayout が呼び出されると、セルのレイアウト属性が作成されてキャッシュされ、適切なタイミングで返されます。これはすべて正しく機能します。
最近、shouldInvalidateLayoutForBoundsChange: にオーバーライドを追加したので、デバイスの回転によってレイアウトの縦横比が変わったときにうまくレイアウトされます。私が今見ているのは、「[UICollectionViewLayoutAttributes copy]: 割り当て解除されたインスタンスに送信されたメッセージ」というメッセージでアプリがクラッシュすることがあるということです。これは、回転イベント中に新しいデータを受信したときに発生します。
私が知る限り、データが受信されて prepareLayout が呼び出された後、ios が layoutAttributesForItemAtIndexPath: メソッドから返された UICollectionViewLayoutAttributes オブジェクトに [copy] を送信しているため、これが発生しています。しかし、私が理解していないのは、iOSがアイテムをすぐにコピーしない理由、またはメモリをリークすることなくアイテムを返した後、適切な期間保持する方法です。
要約すると:
- prepareLayout {
self.myCellAttributes = [NSMutableArray array];
// calculate UICollectionViewLayoutAttributes for each cell,
// and store each in appropriate location ala:
self.myCellAttributes[itemIndex]
}
- layoutAttributesForItemAtIndexPath:(NSIndexPath*)indexPath {
// return appropriate attributes ala:
return self.myCellAttributes[itemIndex];
}
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
CGRect oldBounds = self.collectionView.bounds;
return CGRectGetHeight(newBounds) != CGRectGetHeight(oldBounds);
}
私の最初の修正の試みは次のとおりです。
-(void)prepareForAnimatedBoundsChange:(CGRect)oldBounds {
self.retainedAttributes = self.myCellAttributes;
}
-(void)finalizeAnimatedBoundsChange {
self.retainedAttributes = nil;
}
返されたオブジェクトはアニメーションの間保持されるので、その間に新しいデータが入ってきても問題はないと考えられていました。これは動作に明らかな影響を与えていないため、属性が正しい時間保持されるようにする方法がわかりません。
したがって、当分の間、shouldInvalidateForBoundsChange に対して NO を返すだけです。これにより、クラッシュが解消され、セルがスムーズに移行するのではなく新しいサイズに「スナップ」することを除いて、正常に動作します。
アドバイス/提案/ポインタに非常に感謝しています。