进度条 iOS 13
ProgressBar iOS 13
我尝试创建自己的 ProgressView
来支持 iOS 13,但由于某种原因它似乎不起作用。我试过 @State
、@Binding
和普通的 var progress: Progress
,但它根本没有更新。
struct ProgressBar: View {
@Binding var progress: Progress
var body: some View {
VStack(alignment: .leading) {
Text("\(Int(progress.fractionCompleted))% completed")
ZStack {
RoundedRectangle(cornerRadius: 2)
.foregroundColor(Color(UIColor.systemGray5))
.frame(height: 4)
GeometryReader { metrics in
RoundedRectangle(cornerRadius: 2)
.foregroundColor(.blue)
.frame(width: metrics.size.width * CGFloat(progress.fractionCompleted))
}
}.frame(height: 4)
Text("\(progress.completedUnitCount) of \(progress.totalUnitCount)")
.font(.footnote)
.foregroundColor(.gray)
}
}
}
在我的内容视图中,我添加了 iOS 14 变体和 iOS 13 支持变体。它们看起来一样,但 iOS 13 变体没有任何改变。
struct ContentView: View {
@State private var progress = Progress(totalUnitCount: 10)
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
VStack {
ProgressBar(progress: $progress)
.padding()
.onReceive(timer) { timer in
progress.completedUnitCount += 1
if progress.isFinished {
self.timer.upstream.connect().cancel()
progress.totalUnitCount = 500
}
}
if #available(iOS 14, *) {
ProgressView(progress)
.padding()
.onReceive(timer) { timer in
progress.completedUnitCount += 1
if progress.isFinished {
self.timer.upstream.connect().cancel()
progress.totalUnitCount = 500
}
}
}
}
}
}
iOS 14 变体有效,但我的 iOS 13 实施失败。有人可以帮助我吗?
Progress 是一个 NSObject,它不是一个结构,所以 state 对它不起作用。您必须使用 KVO 来观察 Progress 的变化并重定向到 SwiftUI 视图的真实来源。
这是可能解决方案的简化演示。使用 Xcode 12.1 / iOS 14.1
测试
class ProgressBarViewModel: ObservableObject {
@Published var fractionCompleted: Double
let progress: Progress
private var observer: NSKeyValueObservation!
init(_ progress: Progress) {
self.progress = progress
self.fractionCompleted = progress.fractionCompleted
observer = progress.observe(\.completedUnitCount) { [weak self] (sender, _) in
self?.fractionCompleted = sender.fractionCompleted
}
}
}
struct ProgressBar: View {
@ObservedObject private var vm: ProgressBarViewModel
init(_ progress: Progress) {
self.vm = ProgressBarViewModel(progress)
}
var body: some View {
VStack(alignment: .leading) {
Text("\(Int(vm.fractionCompleted * 100))% completed")
ZStack {
RoundedRectangle(cornerRadius: 2)
.foregroundColor(Color(UIColor.systemGray5))
.frame(height: 4)
GeometryReader { metrics in
RoundedRectangle(cornerRadius: 2)
.foregroundColor(.blue)
.frame(width: metrics.size.width * CGFloat(vm.fractionCompleted))
}
}.frame(height: 4)
Text("\(vm.progress.completedUnitCount) of \(vm.progress.totalUnitCount)")
.font(.footnote)
.foregroundColor(.gray)
}
}
}
并更新调用位置以使用相同的构造函数
struct ContentView: View {
@State private var progress = Progress(totalUnitCount: 10)
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
VStack {
ProgressBar(progress) // << here !!
// ... other code
我尝试创建自己的 ProgressView
来支持 iOS 13,但由于某种原因它似乎不起作用。我试过 @State
、@Binding
和普通的 var progress: Progress
,但它根本没有更新。
struct ProgressBar: View {
@Binding var progress: Progress
var body: some View {
VStack(alignment: .leading) {
Text("\(Int(progress.fractionCompleted))% completed")
ZStack {
RoundedRectangle(cornerRadius: 2)
.foregroundColor(Color(UIColor.systemGray5))
.frame(height: 4)
GeometryReader { metrics in
RoundedRectangle(cornerRadius: 2)
.foregroundColor(.blue)
.frame(width: metrics.size.width * CGFloat(progress.fractionCompleted))
}
}.frame(height: 4)
Text("\(progress.completedUnitCount) of \(progress.totalUnitCount)")
.font(.footnote)
.foregroundColor(.gray)
}
}
}
在我的内容视图中,我添加了 iOS 14 变体和 iOS 13 支持变体。它们看起来一样,但 iOS 13 变体没有任何改变。
struct ContentView: View {
@State private var progress = Progress(totalUnitCount: 10)
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
VStack {
ProgressBar(progress: $progress)
.padding()
.onReceive(timer) { timer in
progress.completedUnitCount += 1
if progress.isFinished {
self.timer.upstream.connect().cancel()
progress.totalUnitCount = 500
}
}
if #available(iOS 14, *) {
ProgressView(progress)
.padding()
.onReceive(timer) { timer in
progress.completedUnitCount += 1
if progress.isFinished {
self.timer.upstream.connect().cancel()
progress.totalUnitCount = 500
}
}
}
}
}
}
iOS 14 变体有效,但我的 iOS 13 实施失败。有人可以帮助我吗?
Progress 是一个 NSObject,它不是一个结构,所以 state 对它不起作用。您必须使用 KVO 来观察 Progress 的变化并重定向到 SwiftUI 视图的真实来源。
这是可能解决方案的简化演示。使用 Xcode 12.1 / iOS 14.1
测试class ProgressBarViewModel: ObservableObject {
@Published var fractionCompleted: Double
let progress: Progress
private var observer: NSKeyValueObservation!
init(_ progress: Progress) {
self.progress = progress
self.fractionCompleted = progress.fractionCompleted
observer = progress.observe(\.completedUnitCount) { [weak self] (sender, _) in
self?.fractionCompleted = sender.fractionCompleted
}
}
}
struct ProgressBar: View {
@ObservedObject private var vm: ProgressBarViewModel
init(_ progress: Progress) {
self.vm = ProgressBarViewModel(progress)
}
var body: some View {
VStack(alignment: .leading) {
Text("\(Int(vm.fractionCompleted * 100))% completed")
ZStack {
RoundedRectangle(cornerRadius: 2)
.foregroundColor(Color(UIColor.systemGray5))
.frame(height: 4)
GeometryReader { metrics in
RoundedRectangle(cornerRadius: 2)
.foregroundColor(.blue)
.frame(width: metrics.size.width * CGFloat(vm.fractionCompleted))
}
}.frame(height: 4)
Text("\(vm.progress.completedUnitCount) of \(vm.progress.totalUnitCount)")
.font(.footnote)
.foregroundColor(.gray)
}
}
}
并更新调用位置以使用相同的构造函数
struct ContentView: View {
@State private var progress = Progress(totalUnitCount: 10)
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
VStack {
ProgressBar(progress) // << here !!
// ... other code