Last active
May 11, 2023 12:11
-
-
Save tclementdev/c402bf5fddd8570287874333bc45a474 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
import SwiftUI | |
// This is an example of how to keep the ObservableObjects near the root of the view hierarchy | |
// and dispatch actions from any view easily without having to pass too many things down. This | |
// helps keep the views simple and makes previews a lot easier. | |
// | |
// This is inspired from what Apple is doing with `DismissAction`, `OpenURLAction`, `OpenWindowAction`, etc... | |
// The following is a very simple example with only two view-levels and we could pass closures directly, | |
// but this gets really useful when dealing with complex view hierarchies that have many view levels. | |
struct ContentView: View { | |
@StateObject var controller = Controller() | |
var body: some View { | |
SubView() | |
.actions(controller.actions) | |
} | |
} | |
struct SubView: View { | |
@Environment(\.actions) var actions | |
var body: some View { | |
Button("create") { | |
let document = actions.create() | |
print("\(document.name)") | |
} | |
Button("send") { | |
Task { | |
let document = Document(name: "doc") | |
try await actions.send(document) | |
} | |
} | |
} | |
} | |
struct Document { | |
let name: String | |
} | |
final class Controller: ObservableObject { | |
var actions: Actions { | |
Actions(create: create, send: send(_:)) | |
} | |
func create() -> Document { | |
// create some document | |
return Document(name: "doc") | |
} | |
func send(_ document: Document) async throws { | |
// send document here | |
} | |
} | |
struct Actions { | |
let create: () -> Document | |
let send: (Document) async throws -> Void | |
} | |
struct ActionsKey: EnvironmentKey { | |
static let defaultValue = Actions(create: { fatalError() }, send: { _ in fatalError() }) | |
} | |
extension EnvironmentValues { | |
var actions: Actions { | |
get { self[ActionsKey.self] } | |
set { self[ActionsKey.self] = newValue } | |
} | |
} | |
extension View { | |
func actions(_ actions: Actions) -> some View { | |
environment(\.actions, actions) | |
} | |
} |
yep, the two pieces are almost the same now :p
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Adjusted.