Files
xcodesApp-mirror/Xcodes/Frontend/Common/ObservingProgressIndicator.swift
2021-01-01 15:36:20 -07:00

63 lines
1.9 KiB
Swift

import Combine
import SwiftUI
/// A ProgressIndicator that reflects the state of a Progress object.
/// This functionality is already built in to ProgressView,
/// but this implementation ensures that changes are received on the main thread.
@available(iOS 14.0, macOS 11.0, *)
public struct ObservingProgressIndicator: View {
let controlSize: NSControl.ControlSize
let style: NSProgressIndicator.Style
@StateObject private var progress: ProgressWrapper
public init(
_ progress: Progress,
controlSize: NSControl.ControlSize,
style: NSProgressIndicator.Style
) {
_progress = StateObject(wrappedValue: ProgressWrapper(progress: progress))
self.controlSize = controlSize
self.style = style
}
class ProgressWrapper: ObservableObject {
var progress: Progress
var cancellable: AnyCancellable!
init(progress: Progress) {
self.progress = progress
cancellable = progress
.publisher(for: \.fractionCompleted)
.receive(on: RunLoop.main)
.sink { [weak self] _ in self?.objectWillChange.send() }
}
}
public var body: some View {
ProgressIndicator(
minValue: 0.0,
maxValue: 1.0,
doubleValue: progress.progress.fractionCompleted,
controlSize: controlSize,
isIndeterminate: progress.progress.isIndeterminate,
style: style
)
}
}
@available(iOS 14.0, macOS 11.0, *)
struct ObservingProgressBar_Previews: PreviewProvider {
static var previews: some View {
Group {
ObservingProgressIndicator(
configure(Progress(totalUnitCount: 100)) {
$0.completedUnitCount = 40
},
controlSize: .small,
style: .spinning
)
}
.previewLayout(.sizeThatFits)
}
}