/SwiftUI-RenderLock

Precise control of redrawing a view in SwiftUI

Primary LanguageSwiftMIT LicenseMIT

SwiftUI Render Lock

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.

Example

render

Usage

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()
            }
        }
    }
}

How it works

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.

But Wait, There's More!

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.