Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,16 +263,16 @@ However, it's still really easy: You have to conform your class to the `Loadable
@Published var numbers: LoadableState<[Int]> = .absent

func loadNumbers() {
// Call the load method from the LoadableSupport protocol
load(\.numbers) {
// Use the new ergonomic accessor
loadables.numbers.load {
try await Task.sleep(for: .seconds(2))
return [42]
}
}

func loadStreamedNumbers() {
// Call the load method that yields results from the LoadableSupport protocol
load(\.numbers) { yield in
// Call the load method that yields results using the accessor
loadables.numbers.load { yield in
var numbers: [Int] = []
for await number in [42, 73].publisher.values {
try await Task.sleep(for: .seconds(1))
Expand All @@ -283,7 +283,7 @@ However, it's still really easy: You have to conform your class to the `Loadable
}

func cancelLoading() {
cancel(\.numbers)
loadables.numbers.cancel()
}
}
```
Expand Down Expand Up @@ -426,21 +426,21 @@ enum ProcessKind {
@Published var process: Process<ProcessKind> = .idle

func save() {
// Call the run method from the ProcessSupport protocol
run(\.process, as: .save) {
// Use the ergonomic accessor
processes.process.run(as: .save) {
try await save()
}
}

func delete() {
// Call the run method from the ProcessSupport protocol
run(\.process, as: .delete) {
// Use the ergonomic accessor
processes.process.run(as: .delete) {
try await delete()
}
}

func cancelLoading() {
cancel(\.process)
processes.process.cancel()
}
}
```
Expand Down
51 changes: 51 additions & 0 deletions Sources/Processed/Loadable/LoadableSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -548,3 +548,54 @@ extension LoadableSupport {
}
}
}

// MARK: - Ergonomic Accessors

@dynamicMemberLookup
public struct Loadables<Container: LoadableSupport> {
unowned let container: Container

public subscript<Value>(dynamicMember keyPath: ReferenceWritableKeyPath<Container, LoadableState<Value>>) -> LoadableAccessor<Container, Value> {
.init(container: container, keyPath: keyPath)
}
}

public struct LoadableAccessor<Container: LoadableSupport, Value> {
unowned let container: Container
let keyPath: ReferenceWritableKeyPath<Container, LoadableState<Value>>

@MainActor @discardableResult
public func load(
silently runSilently: Bool = false,
priority: TaskPriority? = nil,
@_implicitSelfCapture block: @MainActor @escaping () async throws -> Value
) -> Task<Void, Never> {
container.load(keyPath, silently: runSilently, priority: priority, block: block)
}

@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
@MainActor @discardableResult
public func load(
silently runSilently: Bool = false,
interrupts: [Duration],
priority: TaskPriority? = nil,
@_implicitSelfCapture block: @MainActor @escaping () async throws -> Value,
@_implicitSelfCapture onInterrupt: @MainActor @escaping (_ accumulatedDelay: Duration) throws -> Void
) -> Task<Void, Never> {
container.load(keyPath, silently: runSilently, interrupts: interrupts, priority: priority, block: block, onInterrupt: onInterrupt)
}

@MainActor
public func cancel() {
container.cancel(keyPath)
}

@MainActor
public func reset() {
container.reset(keyPath)
}
}

public extension LoadableSupport {
var loadables: Loadables<Self> { .init(container: self) }
}
74 changes: 74 additions & 0 deletions Sources/Processed/Process/ProcessSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -555,3 +555,77 @@ extension ProcessSupport {
}
}
}

// MARK: - Ergonomic Accessors

@dynamicMemberLookup
public struct Processes<Container: ProcessSupport> {
unowned let container: Container

public subscript<ProcessKind: Equatable>(dynamicMember keyPath: ReferenceWritableKeyPath<Container, ProcessState<ProcessKind>>) -> ProcessAccessor<Container, ProcessKind> {
.init(container: container, keyPath: keyPath)
}
}

public struct ProcessAccessor<Container: ProcessSupport, ProcessKind: Equatable> {
unowned let container: Container
let keyPath: ReferenceWritableKeyPath<Container, ProcessState<ProcessKind>>

@MainActor @discardableResult
public func run(
as process: ProcessKind,
silently runSilently: Bool = false,
priority: TaskPriority? = nil,
@_implicitSelfCapture block: @MainActor @escaping () async throws -> Void
) -> Task<Void, Never> {
container.run(keyPath, as: process, silently: runSilently, priority: priority, block: block)
}

@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
@MainActor @discardableResult
public func run(
as process: ProcessKind,
silently runSilently: Bool = false,
interrupts: [Duration],
priority: TaskPriority? = nil,
@_implicitSelfCapture block: @MainActor @escaping () async throws -> Void,
@_implicitSelfCapture onInterrupt: @MainActor @escaping (_ accumulatedDelay: Duration) throws -> Void
) -> Task<Void, Never> {
container.run(keyPath, as: process, silently: runSilently, interrupts: interrupts, priority: priority, block: block, onInterrupt: onInterrupt)
}

@MainActor @discardableResult
public func run(
silently runSilently: Bool = false,
priority: TaskPriority? = nil,
@_implicitSelfCapture block: @MainActor @escaping () async throws -> Void
) -> Task<Void, Never> where ProcessKind == SingleProcess {
container.run(keyPath, silently: runSilently, priority: priority, block: block)
}

@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
@MainActor @discardableResult
public func run(
silently runSilently: Bool = false,
interrupts: [Duration],
priority: TaskPriority? = nil,
@_implicitSelfCapture block: @MainActor @escaping () async throws -> Void,
@_implicitSelfCapture onInterrupt: @MainActor @escaping (_ accumulatedDelay: Duration) throws -> Void
) -> Task<Void, Never> where ProcessKind == SingleProcess {
container.run(keyPath, silently: runSilently, interrupts: interrupts, priority: priority, block: block, onInterrupt: onInterrupt)
}

@MainActor
public func cancel() {
container.cancel(keyPath)
}

@MainActor
public func reset() {
container.reset(keyPath)
}
}

public extension ProcessSupport {
var processes: Processes<Self> { .init(container: self) }
}
Loading