Skip to content

Commit 8e6e875

Browse files
committed
move dynamicMemberLookup from Values to ProgressManager, add setter methods for totalCount and completedCount, remove withProperties closure
1 parent c5613b3 commit 8e6e875

File tree

8 files changed

+571
-835
lines changed

8 files changed

+571
-835
lines changed

Sources/FoundationEssentials/ProgressManager/ProgressManager+Interop.swift

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,7 @@ internal final class NSProgressBridge: Progress, @unchecked Sendable {
187187
self.progress = progress
188188
super.init(parent: nil, userInfo: nil)
189189

190-
managerBridge.withProperties { properties in
191-
properties.completedCount = Int(progress.completedUnitCount)
192-
}
190+
managerBridge.completedCount(Int(progress.completedUnitCount))
193191

194192
let position = manager.addChild(
195193
child: managerBridge,
@@ -202,11 +200,8 @@ internal final class NSProgressBridge: Progress, @unchecked Sendable {
202200
// Overrides the _updateChild func that Foundation.Progress calls to update parent
203201
// so that the parent that gets updated is the ProgressManager parent
204202
override func _updateChild(_ child: Foundation.Progress, fraction: _NSProgressFractionTuple, portion: Int64) {
205-
managerBridge.withProperties { properties in
206-
properties.totalCount = Int(fraction.next.total)
207-
properties.completedCount = Int(fraction.next.completed)
208-
}
209-
203+
managerBridge.totalCount(Int(fraction.next.total))
204+
managerBridge.completedCount(Int(fraction.next.completed))
210205
managerBridge.markSelfDirty()
211206
}
212207
}

Sources/FoundationEssentials/ProgressManager/ProgressManager+Properties+Accessors.swift

Lines changed: 172 additions & 432 deletions
Large diffs are not rendered by default.

Sources/FoundationEssentials/ProgressManager/ProgressManager+State.swift

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,64 @@ extension ProgressManager {
223223
internal mutating func complete(by count: Int) {
224224
selfFraction.completed += count
225225

226+
#if FOUNDATION_FRAMEWORK
227+
switch interopType {
228+
case .interopObservation(let observation):
229+
observation.subprogressBridge?.manager.notifyObservers(
230+
with: .fractionUpdated(
231+
totalCount: selfFraction.total ?? 0,
232+
completedCount: selfFraction.completed
233+
)
234+
)
235+
236+
if let _ = observation.reporterBridge {
237+
notifyObservers(
238+
with: .fractionUpdated(
239+
totalCount: selfFraction.total ?? 0,
240+
completedCount: selfFraction.completed
241+
)
242+
)
243+
}
244+
case .interopMirror:
245+
break
246+
default:
247+
break
248+
}
249+
#endif
250+
}
251+
252+
internal mutating func completedCount(_ count: Int) {
253+
selfFraction.completed = count
254+
255+
#if FOUNDATION_FRAMEWORK
256+
switch interopType {
257+
case .interopObservation(let observation):
258+
observation.subprogressBridge?.manager.notifyObservers(
259+
with: .fractionUpdated(
260+
totalCount: selfFraction.total ?? 0,
261+
completedCount: selfFraction.completed
262+
)
263+
)
264+
265+
if let _ = observation.reporterBridge {
266+
notifyObservers(
267+
with: .fractionUpdated(
268+
totalCount: selfFraction.total ?? 0,
269+
completedCount: selfFraction.completed
270+
)
271+
)
272+
}
273+
case .interopMirror:
274+
break
275+
default:
276+
break
277+
}
278+
#endif
279+
}
280+
281+
internal mutating func totalCount(_ count: Int?) {
282+
selfFraction.total = count
283+
226284
#if FOUNDATION_FRAMEWORK
227285
switch interopType {
228286
case .interopObservation(let observation):

Sources/FoundationEssentials/ProgressManager/ProgressManager.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ internal import _FoundationCollections
2323

2424
/// An object that conveys ongoing progress to the user for a specified task.
2525
@available(FoundationPreview 6.2, *)
26+
@dynamicMemberLookup
2627
@Observable public final class ProgressManager: Sendable {
2728

2829
internal let state: Mutex<State>
@@ -191,6 +192,36 @@ internal import _FoundationCollections
191192
}
192193
}
193194

195+
public func completedCount(_ count: Int) {
196+
let parents: [ParentState]? = state.withLock { state in
197+
guard state.selfFraction.completed != count else {
198+
return nil
199+
}
200+
201+
state.completedCount(count)
202+
203+
return state.parents
204+
}
205+
if let parents = parents {
206+
markSelfDirty(parents: parents)
207+
}
208+
}
209+
210+
public func totalCount(_ count: Int?) {
211+
let parents: [ParentState]? = state.withLock { state in
212+
guard state.selfFraction.total != count else {
213+
return nil
214+
}
215+
216+
state.totalCount(count)
217+
218+
return state.parents
219+
}
220+
if let parents = parents {
221+
markSelfDirty(parents: parents)
222+
}
223+
}
224+
194225
// MARK: Internal Observation Support for Extensions
195226

196227
/// Provides access to the observation registrar for use in extensions.

Sources/FoundationEssentials/ProgressManager/ProgressReporter.swift

Lines changed: 92 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ import Observation
1616
///
1717
/// It is read-only and can be added as a child of another ProgressManager.
1818
@available(FoundationPreview 6.2, *)
19+
@dynamicMemberLookup
1920
@Observable public final class ProgressReporter: Sendable, Hashable, Equatable, CustomStringConvertible, CustomDebugStringConvertible {
2021

21-
public typealias Values = ProgressManager.Values
2222
public typealias Property = ProgressManager.Property
2323

2424
/// The total units of work.
@@ -82,13 +82,6 @@ import Observation
8282
return self.description
8383
}
8484

85-
/// Reads properties that convey additional information about progress.
86-
public func withProperties<T, E: Error>(
87-
_ closure: (sending Values) throws(E) -> sending T
88-
) throws(E) -> T {
89-
return try manager.getProperties(closure)
90-
}
91-
9285
/// Returns a summary for the specified integer property across the progress subtree.
9386
///
9487
/// This method aggregates the values of a custom integer property from the underlying progress manager
@@ -173,6 +166,97 @@ import Observation
173166
return manager.summary(of: property)
174167
}
175168

169+
/// Gets or sets custom integer properties.
170+
///
171+
/// This subscript provides read-write access to custom progress properties where both the value
172+
/// and summary types are `Int`. If the property has not been set, the getter returns the
173+
/// property's default value.
174+
///
175+
/// - Parameter key: A key path to the custom integer property type.
176+
public subscript<P: Property>(dynamicMember key: KeyPath<ProgressManager.Properties, P.Type>) -> Int where P.Value == Int, P.Summary == Int {
177+
get {
178+
manager[dynamicMember: key]
179+
}
180+
}
181+
182+
/// Gets or sets custom unsigned integer properties.
183+
///
184+
/// This subscript provides read-write access to custom progress properties where both the value
185+
/// and summary types are `UInt64`. If the property has not been set, the getter returns the
186+
/// property's default value.
187+
///
188+
/// - Parameter key: A key path to the custom unsigned integer property type.
189+
public subscript<P: Property>(dynamicMember key: KeyPath<ProgressManager.Properties, P.Type>) -> UInt64 where P.Value == UInt64, P.Summary == UInt64 {
190+
get {
191+
manager[dynamicMember: key]
192+
}
193+
}
194+
195+
/// Gets or sets custom double properties.
196+
///
197+
/// This subscript provides read-write access to custom progress properties where both the value
198+
/// and summary types are `Double`. If the property has not been set, the getter returns the
199+
/// property's default value.
200+
///
201+
/// - Parameter key: A key path to the custom double property type.
202+
public subscript<P: Property>(dynamicMember key: KeyPath<ProgressManager.Properties, P.Type>) -> P.Value where P.Value == Double, P.Summary == Double {
203+
get {
204+
manager[dynamicMember: key]
205+
}
206+
}
207+
208+
/// Gets or sets custom string properties.
209+
///
210+
/// This subscript provides read-write access to custom progress properties where the value
211+
/// type is `String?` and the summary type is `[String?]`. If the property has not been set,
212+
/// the getter returns the property's default value.
213+
///
214+
/// - Parameter key: A key path to the custom string property type.
215+
public subscript<P: Property>(dynamicMember key: KeyPath<ProgressManager.Properties, P.Type>) -> String? where P.Value == String?, P.Summary == [String?] {
216+
get {
217+
manager[dynamicMember: key]
218+
}
219+
}
220+
221+
/// Gets or sets custom URL properties.
222+
///
223+
/// This subscript provides read-write access to custom progress properties where the value
224+
/// type is `URL?` and the summary type is `[URL?]`. If the property has not been set,
225+
/// the getter returns the property's default value.
226+
///
227+
/// - Parameter key: A key path to the custom URL property type.
228+
public subscript<P: Property>(dynamicMember key: KeyPath<ProgressManager.Properties, P.Type>) -> URL? where P.Value == URL?, P.Summary == [URL?] {
229+
get {
230+
manager[dynamicMember: key]
231+
}
232+
}
233+
234+
/// Gets or sets custom unsigned integer properties.
235+
///
236+
/// This subscript provides read-write access to custom progress properties where the value
237+
/// type is `UInt64` and the summary type is `[UInt64]`. If the property has not been set,
238+
/// the getter returns the property's default value.
239+
///
240+
/// - Parameter key: A key path to the custom unsigned integer property type.
241+
public subscript<P: Property>(dynamicMember key: KeyPath<ProgressManager.Properties, P.Type>) -> UInt64 where P.Value == UInt64, P.Summary == [UInt64] {
242+
get {
243+
manager[dynamicMember: key]
244+
}
245+
}
246+
247+
/// Gets or sets custom duration properties.
248+
///
249+
/// This subscript provides read-write access to custom progress properties where the value
250+
/// type is `Duration` and the summary type is `Duration`. If the property has not been set,
251+
/// the getter returns the property's default value.
252+
///
253+
/// - Parameter key: A key path to the custom duration property type.
254+
public subscript<P: Property>(dynamicMember key: KeyPath<ProgressManager.Properties, P.Type>) -> Duration where P.Value == Duration, P.Summary == Duration {
255+
get {
256+
manager[dynamicMember: key]
257+
}
258+
}
259+
176260
internal let manager: ProgressManager
177261

178262
internal init(manager: ProgressManager) {

0 commit comments

Comments
 (0)