Reputation: 578
I just can´t find out how to get access to custom layout attributes in the apply() method of a custom cell.
I have to implement a custom layout attribute to my CollectionViewLayoutAtrributes
, so I subclassed them. This works well so far:
class TunedLayoutAttributes: UICollectionViewLayoutAttributes {
var customLayoutAttributeValue: CGFloat = 1000
override func copy(with zone: NSZone?) -> Any {
let copy = super.copy(with: zone) as! TunedLayoutAttributes
customLayoutAttributeValue = customLayoutAttributeValue
return copy
}
override func isEqual(_ object: Any?) -> Bool {
if let attributes = object as? TunedLayoutAttributes {
if attributes. customLayoutAttributeValue == customLayoutAttributeValue {
return super.isEqual (object)
}
}
return false
}
}
The value has to dynamically change based on user scroll interaction.
Now I need my custom cells to update their appearance after an invalidateLayout
call from the custom UICollectionViewLayout
class. To my knowledge this usually can also be done by overriding the cells classes apply(_ layoutAttributes: UICollectionViewLayoutAttributes)
method.
Usually like so:
override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
let newFrame = // calculations here. CGRect(....)
layoutAttributes.frame = newFrame
}
Unlike in the apply()
example above my new customLayoutAttributeValue
is (of course?) not part of the layoutAttributes:
in the method.
So I tried to downcast the layoutAttributes to my custom class like so:
override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
let tunedLayoutAttributes = layoutAttributes as! TunedLayoutAttributes
tunedLayoutAttributes.customLayoutAttributeValue = // calculation here.
}
So how do I get access to tunedLayoutAttributes in the apply() method? Any help is appreciated. Thanks for reading!
Upvotes: 2
Views: 1212
Reputation: 3261
You kind of gave the solution to yourself here. UICollectionViewLayoutAttributes
does (of course) not know about customLayoutAttributeValue
, so you have to cast to the appropriate class (TunedLayoutAttributes
, in your case).
Now in order for apply(_:)
to actually give you TunedLayoutAttributes
and not just plain UICollectionViewLayoutAttributes
, you need to tell your UICollectionViewLayout
subclass to use your custom class (TunedLayoutAttributes
) when vending layout attributes for items in the layout.
You do that by overriding class var layoutAttributesClass
in you layout subclass.
Note that if you override layout attributes vending methods (layoutAttributesForElements(in:)
and friends) in your layout subclass, you'd need to return TunedLayoutAttributes
there for the whole thing to work.
Also note that UIKit
frequently copies attributes under the hood when performing collection view layout passes, so make sure your copy
and isEqual
methods are working as expected. (e.g., the attributes objects passed to apply(_:)
are not (necessarily) the objects your layout vended, but rather copies.
As discussed in the comments, you should replace the forcecast as!
with an if let as?
cast to prevent crashes when apply(_:)
actually gets passed plain UICollectionViewLayoutAttributes
.
Upvotes: 4