Cublax
Cublax

Reputation: 1409

ProgressView not rendering SwiftUI

With the following devices (at least, but not with all simulators or devices):

The following code isn't rendering the ProgressView()

import SwiftUI

struct ContentView: View {
    var body: some View {
        Form {
            Section() {
                ProgressView()
            }
        }
        
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Expected Result:

enter image description here

Upvotes: 2

Views: 409

Answers (1)

CouchDeveloper
CouchDeveloper

Reputation: 19106

I can reproduce this erroneous behaviour for a few devices and simulators running certain iOS versions. For example, iOS 15.0.1 on the device, and corresponding iOS 15.0 on the simulator show the same missing ProgressView. I would suggest to file a bug report.

After investigating, it seems to be an issue with starting animations, when the ProgressView is embedded into a Form.

The same erroneous behaviour is shown when replacing ProgressView with this UIKit version LegacyActivityIndicator:

struct LegacyActivityIndicator: UIViewRepresentable {
    let style: UIActivityIndicatorView.Style = .medium

    func makeUIView(
        context: UIViewRepresentableContext<LegacyActivityIndicator>
    ) -> UIActivityIndicatorView {
        UIActivityIndicatorView(style: style)
    }

    func updateUIView(
        _ uiView: UIActivityIndicatorView,
        context: UIViewRepresentableContext<LegacyActivityIndicator>
    ) {
        uiView.startAnimating()
    }
}

The interesting thing is the workaround which makes the LegacyActivityIndicator work properly on devices and simulators where it fails otherwise:

Change func updateUIView(_:context:):

    func updateUIView(
        _ uiView: UIActivityIndicatorView,
        context: UIViewRepresentableContext<LegacyActivityIndicator>
    ) {
        DispatchQueue.main.async {
            uiView.startAnimating()
        }
    }

A pure SwiftUI View will also work on all devices and simulators on all iOS versions which I tested. For example with this (not production ready) SwiftUI view:

public struct MyActivityIndicator: ProgressViewStyle {
    @State private var isAnimating: Bool = false

    public func makeBody(configuration: ProgressViewStyleConfiguration) -> some View {
        VStack {
            ZStack {
                Image(systemName: "arrow.triangle.2.circlepath")
                .rotationEffect(Angle(degrees: isAnimating ? 360 : 0.0))
                .animation(
                    isAnimating ? infiniteAnimation(duration: 1.0) : nil
                )
            }
        }
        .frame(width: 60, height: 60)
        .onAppear {
            isAnimating = true
        }
        .onDisappear {
            isAnimating = false
        }
    }

    private func infiniteAnimation(duration: Double) -> Animation {
        .linear(duration: duration)
        .repeatForever(autoreverses: false)
    }
}

Use it as follows:

        Form {
            Section {
                ProgressView()
                    .progressViewStyle(MyActivityIndicator())
                    .padding()
            }
        }

Upvotes: 3

Related Questions