Skip to content

Instantly share code, notes, and snippets.

@BigZaphod
Created July 29, 2022 16:25
Show Gist options
  • Save BigZaphod/3108c570796d048029a18b343ef3a406 to your computer and use it in GitHub Desktop.
Save BigZaphod/3108c570796d048029a18b343ef3a406 to your computer and use it in GitHub Desktop.
//
// View+Assign.swift
// Created by Sean on 7/29/22.
//
import SwiftUI
// You cannot safely assign to a state variable during view update - such as inside the block of a GeometryReader.
// Rather than do an unsafe hack like DispatchQueue.main.async or resorting to a PreferenceKey or even Combine, we
// can simply defer the assignment to a time when it *is* safe to update State- such as inside of the task block!
// The only requirement here is that the value be Equatable. This ensures that we don't bother updating the binding
// unless the value *actually* changes which saves us time and can also prevent layout update loops. As an added
// bonus, we're using an autoclosure so that if no binding is supplied (your view might have an optional binding),
// the value need not even be computed in the first place. Much efficient. Very buttery. Such performance!
extension View {
@ViewBuilder func assign<Value: Equatable>(_ value: @autoclosure ()->Value, to binding: Binding<Value>?) -> some View {
if let binding {
let computedValue = value()
task(id: computedValue) {
binding.wrappedValue = computedValue
}
} else {
self
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment