I would like to create a property wrapper which is invalidating the layout of my UICollectionViewLayout
.
Therefore I created this property wrapper
@propertyWrapper
class LayoutInvalidating {
private let layout: UICollectionViewLayout
init(layout: UICollectionViewLayout) {
self.layout = layout
self.wrappedValue = layout
}
var wrappedValue: UICollectionViewLayout {
didSet {
self.layout.invalidateLayout()
}
}
}
Then I would like to use it as follows
final class VehicleControlsCollectionViewLayout: UICollectionViewLayout {
@LayoutInvalidating(layout: self) // self is not alive
public var itemSize: CGSize = .init(width: 70, height: 70)
}
Everytime the property is set I would like to call self.invalidateLayout()
. Any ideas how I can access self when it's existing?
This property can have any type you want. To access this property, you need to add a $ prefix to the property name. To explain how it works, we use an example from the Combine framework. The @Published property wrapper creates a publisher for the property and returns it as a projected value.
You can create a Property Wrapper by defining a struct and marking it with the @propertyWrapper attribute. The attribute will require you to add a wrappedValue property to provide a return value on the implementation level.
The underlying value referenced by the binding variable.
@Published is one of the property wrappers in SwiftUI that allows us to trigger a view redraw whenever changes occur. You can use the wrapper combined with the ObservableObject protocol, but you can also use it within regular classes.
Unfortunately, it is not possible to add self
to @propertyWrapper
s init
- this property is create during creation of self
.
It will be possible in the future - look at proposal (Referencing the enclosing 'self' in a wrapper type).
If you are looking for some kind of workaround, you can consider add function to your property wrapper and call this function after init in your class:
@propertyWrapper
class LayoutInvalidating<Value> {
private var layout: UICollectionViewLayout?
init(wrappedValue: Value) {
self.wrappedValue = wrappedValue
}
func configure(with layout: UICollectionViewLayout?) {
self.layout = layout
}
var wrappedValue: Value {
didSet {
layout?.invalidateLayout()
}
}
}
final class VehicleControlsCollectionViewLayout: UICollectionViewLayout {
@LayoutInvalidating
public var itemSize: CGSize = .init(width: 70, height: 70)
override init() {
super.init()
_itemSize.configure(with: self)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With