A simple library to enable precise control of rendering a view.
Sometimes you may want to pause all view updates despite how the environment is changing. This library makes it easy to pause or manually trigger view redrawing.
This library is so simple, you can just copy/paste the relevent struct or depend on it as a Swift package.
First add the package to your project.
import RenderLock
struct Example: View {
@State var count = 0
@State var lock = false
var body: some View {
VStack {
HStack {
Text("\(count)")
.renderLocked(with: $lock)
}
Button("+1") {
count += 1
}
Button("Lock") {
lock.toggle()
}
}
}
}
SwiftUI provides the equatable()
method:
Prevents the view from updating its child view when its new value is the same as its old value.
So we can exploit this behavior by wrapping any view in an equatable wrapper and then explicitly toggling it's equality with a @State
variable. RenderLocked
will only redraw it's subviews when lock
is false. It works like this:
@Binding var lock: Bool
static func == (lhs: LockedView, rhs: LockedView) -> Bool {
if rhs.lock {
return true
}
return false
}
A beneficial side effect of this behavior is the view is signaled to redraw when unlocked. So any view updates that were previously blocked will be applied immediately.
This library also includes RenderDeferred
which uses the same concept, but instead of locking or unlocking view updates, it only updates when signaled: RenderDeferred(with: $signal)
where signal
is a Bool
.
This can be useful if you want to tie all view updates to a timer, or another control.