Skip to content

Instantly share code, notes, and snippets.

@Tunous
Last active July 11, 2023 08:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tunous/c813e875f4c90ce146ef5a50ab118f54 to your computer and use it in GitHub Desktop.
Save Tunous/c813e875f4c90ce146ef5a50ab118f54 to your computer and use it in GitHub Desktop.
Equatable search action
import SwiftUI
struct ContentView: View {
@State private var id = UUID()
@State private var isOn = false
var body: some View {
VStack {
// Changing this toggle will cause child views to update colors
Toggle("Toggle", isOn: $isOn)
ChildWithEquatable() // This view correctly stays with unchanged color
ChildWithRegular()
ChildWithClosure()
}
.environment(\.equatableAction, EquatableAction(id: id, action: {
doWork()
}))
.environment(\.action, Action(action: {
doWork()
}))
.environment(\.closure, {
doWork()
})
}
private func doWork() {
// Removing reference to this function from above closures (for \.action and \.closure)
// will fix the issue
}
}
struct ChildWithEquatable: View {
@Environment(\.equatableAction) private var action
var body: some View {
Color(red: .random(in: 0..<1), green: .random(in: 0..<1), blue: .random(in: 0..<1))
}
}
struct ChildWithRegular: View {
@Environment(\.action) private var action
var body: some View {
Color(red: .random(in: 0..<1), green: .random(in: 0..<1), blue: .random(in: 0..<1))
}
}
struct ChildWithClosure: View {
@Environment(\.closure) private var action
var body: some View {
Color(red: .random(in: 0..<1), green: .random(in: 0..<1), blue: .random(in: 0..<1))
}
}
struct EquatableAction: Equatable {
private let id: UUID
private let action: () -> Void
init(id: UUID, action: @escaping () -> Void) {
self.id = id
self.action = action
}
func callAsFunction() {
action()
}
static func ==(lhs: EquatableAction, rhs: EquatableAction) -> Bool {
lhs.id == rhs.id
}
}
struct Action {
private let action: () -> Void
init(action: @escaping () -> Void) {
self.action = action
}
func callAsFunction() {
action()
}
}
private struct EquatableActionKey: EnvironmentKey {
static var defaultValue: EquatableAction = EquatableAction(id: UUID(), action: {})
}
private struct ActionKey: EnvironmentKey {
static var defaultValue: Action = Action(action: {})
}
private struct ClosureKey: EnvironmentKey {
static var defaultValue: () -> Void = {}
}
extension EnvironmentValues {
var equatableAction: EquatableAction {
get { self[EquatableActionKey.self] }
set { self[EquatableActionKey.self] = newValue }
}
var action: Action {
get { self[ActionKey.self] }
set { self[ActionKey.self] = newValue }
}
var closure: () -> Void {
get { self[ClosureKey.self] }
set { self[ClosureKey.self] = newValue }
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment