0

I want to make an infinite scroll post view. I am using ScrollView + LazyVStack (if i use a List then the behavior is the same). The Row in this example is similar to the Row in my real project - text, then picture, then more text in vertical stack. The problem is that when I scroll, when the picture appears, twitching starts. I noticed that if you leave only the picture and remove the VStack, then the twitching becomes less, but they are still there. In this example, I am using AsyncImage from ios 15, but the same behavior with pictures from Nuke, SDWebImage and others. How can i get smooth scrolling without twitching?

import SwiftUI

struct ContentView: View {
    
    let urls: [URL] = [
        URL(string: "https://klike.net/uploads/posts/2019-05/1556945414_2.jpg")!,
        URL(string: "https://klike.net/uploads/posts/2018-12/1544426537_1.jpg")!,
        URL(string: "https://klike.net/uploads/posts/2018-12/1544426563_6.jpg")!,
        URL(string: "https://klike.net/uploads/posts/2018-12/1544426524_3.jpg")!,
        URL(string: "https://klike.net/uploads/posts/2018-12/1544426502_5.jpg")!,
        URL(string: "https://klike.net/uploads/posts/2018-12/1544426571_23.jpg")!,
        URL(string: "https://klike.net/uploads/posts/2018-12/1544426508_4.jpg")!,
        URL(string: "https://klike.net/uploads/posts/2018-12/1544426506_2.jpg")!,
        URL(string: "https://klike.net/uploads/posts/2018-12/1544426569_9.jpg")!
    ]
    
    var body: some View {
        ScrollView {
            LazyVStack {
                ForEach(urls, id: \.self) { url in
                    Row(url: url)
                }
            }
        }
    }
}

struct Row: View {
    let url: URL
    let width = UIScreen.main.bounds.width
    
    var body: some View {
        VStack(spacing: 0) {
            Text(url.absoluteString)
                .font(.body)
            
            // Here can be Nuke, SDWebImage or something else
            AsyncImage(url: url) { image in
                image
                    .resizable()
                    .scaledToFit()
            } placeholder: {
                ProgressView()
            }
            .frame(width: width, height: width * 1.666666666666667) // <- 800/480 image size
            
            Text(url.absoluteString)
                .font(.callout)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
1
  • Have you tried using a placeholder image and then substituting the actual image when downloaded? Your issue is that it obviously takes time to download the images. Also, you should use a separate class to download the images Commented Aug 3, 2021 at 14:07

1 Answer 1

0

As the user scrolls, every time a row is visible the app requests the same image repeatedly. Therefore, I believe you need to cache downloaded images.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.