Created
July 29, 2022 16:25
-
-
Save BigZaphod/3108c570796d048029a18b343ef3a406 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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