Last active
July 11, 2023 08:14
-
-
Save Tunous/c813e875f4c90ce146ef5a50ab118f54 to your computer and use it in GitHub Desktop.
Equatable search action
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
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