2

I have a problem with the asyncimage.

Here is the link to the files https://www.vadimbulavin.com/asynchronous-swiftui-image-loading-from-url-with-combine-and-swift/

The image of the bottom bar does not change on button action. How could I fix it and could you explain it?

podcastIndex is @Publisched inside the PodcastParser Class

The text changes and it's no problem, but the image is alway the same.

Here is my ContentView:

struct ContentView: View {

@ObservedObject var podcastParser = PodcastParser()

init() {
    podcastParser.loadData()
}

var body: some View {
    NavigationView {
        List(podcastParser.podcasts.indices) { index in
            HStack {
                Button(action: {
                    podcastParser.podcastIndex = index
                    print(podcastParser.podcasts[podcastParser.podcastIndex].imageUrl)
                }) {
                    HStack {
                        AsyncImage(
                            url: podcastParser.podcasts[index].imageUrl,
                            placeholder: {
                                Text("Loading...")
                            },
                            image: { Image(uiImage: $0).resizable() }
                        )
                        .scaledToFit()
                        .frame(width: 50, height: 50)
                        Text(podcastParser.podcasts[index].name)
                    }
                }
            }
        }
    }
    VStack {
        HStack {
            AsyncImage(
                url: podcastParser.podcasts[podcastParser.podcastIndex].imageUrl,
                placeholder: {
                    Text("Loading...")
                },
                image: { Image(uiImage: $0).resizable() }
            )
            .scaledToFit()
            .frame(width: 50, height: 50)
            Text(podcastParser.podcasts[podcastParser.podcastIndex].name)
        }
    }
}
}
Leff
  • 43
  • 4

1 Answers1

5

Generally when you have such problems, there's always a brute force solution to force view update using id modifier.

AsyncImage(
    url: podcastParser.podcasts[podcastParser.podcastIndex].imageUrl,
    placeholder: {
        Text("Loading...")
    },
    image: { Image(uiImage: $0).resizable() }
).id(podcastParser.podcasts[podcastParser.podcastIndex].imageUrl)

With system AsyncImage this would be the only solution, but in your case you're using open source solition, so can modify it to fix the problem.

Replacing StateObject with ObservedObject in AsyncImage.swift solves the problem in this case. I'm using same approach with this library and haven't faced any issues so far.

Phil Dukhov
  • 67,741
  • 15
  • 184
  • 220
  • now I have another problem! After Tap to the List-Button Element all my images inside of List-Element will be reset to the placeholder image. (view will be rebuild, I think). If I change back to `StateObject` is everything fine. Any idea? – Leff Aug 26 '21 at 14:35
  • @Leff you mean when you tap on the cell to select bottom image? It doesn't happen to me.. Have you took `AsyncImage` source code from from [this repository](https://github.com/V8tr/AsyncImage)? – Phil Dukhov Aug 26 '21 at 14:47
  • yes, I used the same repository. I use this case inside other project and the view get all data over `@EnvironmentObject var radioPlayer: RadioPlayer` Maybe it makes problems inside of the parent object? – Leff Aug 26 '21 at 14:53
  • @Leff When you updated your list in your model and using `podcastParser.podcasts.indices` in your `List` or `ForEach` this would rebuild all the cells. In case with `@StateObject` it not updating same as it doesn't update at the bottom, so it's a bug, not a feature =) Create a new question, because the answer is too big for a comment. – Phil Dukhov Aug 26 '21 at 15:14
  • 1
    okay, I will do it tomorrow! I've just rebuild the structure of the main project to the playground and it works without problems. Strange, that the same structure doesn't work inside the main project. I have to find a bug somewhere... ;) – Leff Aug 26 '21 at 16:07