onevcat / Kingfisher

A lightweight, pure-Swift library for downloading and caching images from the web.
MIT License
23.4k stars 2.66k forks source link

KFImage in SwiftUI does not respect transitions, just appears right away on iOS 16 #1987

Open IvanShah opened 2 years ago

IvanShah commented 2 years ago

Issue Description

KFImages always show up immediately in their final position and do not transition or animate in SwiftUI. I tried the forceTransition modifier and that doesn't resolve the issue. Also tried different animation and transition settings but nothing helps. On iOS 15 and 14 it works well. The same issue as https://github.com/onevcat/Kingfisher/issues/1762.

onevcat commented 2 years ago

Tried with the "Transition" sample in the demo app on iOS 16, but not reproducible:

https://user-images.githubusercontent.com/1019875/191277849-508d4d9b-36de-4fec-9f0d-caa6b3a686a8.mp4

Can you check the sample view to see if you can find anything? Or can you paste some code snippets to help us understand the situation better?

Thanks!

IvanShah commented 2 years ago

I think I found how reproduce this, in sample app you use UIHostingController, if SwiftUI View inside UIHostingController transition works. But if app used SwiftUI App life cycle - transition of KFImage is broken.

scutiuys commented 2 years ago

I think the same way When the image download is completed or changed image data in SwiftUI lifecycle, it seems to end the transition animation

onevcat commented 2 years ago

Tried to created a new SwiftUI app and the following code snippet. Still no luck to reproduce and things goes fine as I can see. Can I get a sample in which this issue can be reproduced?

struct ContentView: View {
    @State private var showDetails = false

    var body: some View {
        VStack {
            Button(showDetails ? "Hide" : "Show") {
                withAnimation {
                    showDetails.toggle()
                }
            }
            if showDetails {
                KFImage(.init(string: "https://raw.githubusercontent.com/onevcat/Kingfisher-TestImages/master/DemoAppImage/Loading/kingfisher-1.jpg"))
                    .transition(.slide)
            }
            Spacer()
        }.frame(height: 500)
    }
}

https://user-images.githubusercontent.com/1019875/194715712-d20dffda-47b3-4dca-b29a-bb0dcf6854ea.mp4

IvanShah commented 2 years ago

I found how to reproduce it. It's implicit animation. The same effect if animation inside transition.

struct ContentView: View {
    @State private var showDetails = false

    var body: some View {
        ZStack {
            if showDetails {
                KFImage(.init(string: "https://raw.githubusercontent.com/onevcat/Kingfisher-TestImages/master/DemoAppImage/Loading/kingfisher-1.jpg"))
                    .resizable()
                    .ignoresSafeArea()
                    .transition(.slide)
            }

            Button(showDetails ? "Hide" : "Show") {
                showDetails.toggle()
            }
        }
        .animation(.default, value: showDetails)
    }
}

https://user-images.githubusercontent.com/68146159/194865210-954c058f-7ad8-4eff-9c58-ef19cc4e314e.mov