0

How can I achieve such a scenario.

  1. Using the AsyncImage I load the url.
  2. Progress view turns around as placeholder
  3. After 2 seconds we don't get an error
  4. Our ProgressView changes to an image

This is a code:

AsyncImage(url: exampleURL) { phase in
    if let image = phase.image {
        image
            .imageModifier()
    } else if phase.error != nil {
        Image("example_image")
            .imageModifier()
    } else {
        ProgressView()
            .font(.largeTitle)
    }
}

There is any short and clean solution of I need to using custom implementation async image and using for example taskgroups? Thanks for any ideas.

miltenkot
  • 29
  • 4
  • 1
    You would have to create your own. – lorem ipsum Apr 25 '23 at 12:14
  • ok I go one that's pleases me. 1. https://stackoverflow.com/questions/58804696/swiftui-viewmodifier-where-content-is-an-image 2. asyncWithTimeout method from objc.io advanced swift and their connection. But too bad it's not on the library side. – miltenkot Apr 25 '23 at 14:19

1 Answers1

0

You could try this approach, using a Timer with onReceive, works well for me. Set an appropriate timeRemaining. After that time has elapsed, the AsyncImage will present the chosen image ("timer"), if the image is downloaded before that time, that image will be displayed.

struct ContentView: View {
    let url = URL(string: "https://www.trinum.com/ibox/ftpcam/mega_mtgenevre_sommet-des-gondrans.jpg")!

    let timer = Timer.publish(every: 1.0, on: .main, in: .common).autoconnect()
    @State var timeRemaining = 2
    
    var body: some View {
        AsyncImage(url: url) { phase in
            if timeRemaining <= 0 {
                Image(systemName: "timer")
            } else {
                switch phase {
                    case .empty: ProgressView()
                    case .success(let image):
                      image.resizable()
                        .onAppear { timer.upstream.connect().cancel() }
                    case .failure:
                      Image(systemName: "wifi.slash")
                        .onAppear { timer.upstream.connect().cancel() }
                    @unknown default: EmptyView()
                }
            }
        }
        .onReceive(timer) { _ in
            if timeRemaining > 0 {
                timeRemaining -= 1
            } else {
                timer.upstream.connect().cancel()
            }
        }
    }
    
}