onevcat / Kingfisher

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

HighRes Image Loading Failure in iOS 18 with KFImage in List/ForEach #2316

Closed goojoob closed 1 week ago

goojoob commented 1 week ago

Check List

Thanks for considering to open an issue. Before you submit your issue, please confirm these boxes are checked.

Issue Description

What

On iOS 18 (Xcode 16.0), KFImages frequently fail to show up when used inside List/ForEach. I have high quality images and use the DownsamplingImageProcessor, but only some of them load successfully, while the rest remain stuck in a loading state, and I see the following log: nw_connection_add_timestamp_locked_on_nw_queue [C1] Hit maximum timestamp count, will start dropping events

Interestingly, if I switch from WiFi to 5G, the images start loading again, but the loading stalls once more after a few additional images, showing again the same message log.

Reproduce

@State var allImages: [String] = //the content of this array is in https://oldschool.cat/allImages.swift please copy paste here the content

    var body: some View {
        NavigationStack {
            List {
                ForEach(allImages, id: \.self) { release in
                    if let image = URL(string: release) {
                        KFImage(image)
                            .placeholder {
                                ProgressView()
                            }
                            .retry(maxCount: 3, interval: .seconds(3))
                            .setProcessor(DownsamplingImageProcessor(size: CGSize(width: 100, height: 100)))
                    }
                }
            }
        }
    }

Other Comment

You can check the behaviour in this video: https://youtu.be/043Uy0i9LcE

onevcat commented 1 week ago

Upon investigating the URLs provided, I found that the server is returning HTTP status code 429 (Too Many Requests), indicating that the requests are being rate-limited.

Error: responseError(reason: Kingfisher.KingfisherError.ResponseErrorReason.invalidHTTPStatusCode(response: <NSHTTPURLResponse: 0x6000003116a0> { URL: https://i.discogs.com/....NC5qcGVn.jpeg } { 
    Status Code: 429, Headers 
{
    "Alt-Svc" =     (
        "h3=\":443\"; ma=86400"
....
}

This status code 429 is specifically designed to indicate when a user has exceeded the allowed number of requests within a given time period. The server implements these rate limits to prevent excessive concurrent requests (such as multiple simultaneous image loads). This explains why switching networks temporarily resolves the issue - the new network connection presents a different client IP address to the server, effectively resetting the rate limit counter.

Since this is a server-side rate limiting mechanism rather than a Kingfisher-related issue, I recommend closing this ticket. Please don't hesitate to reach out if you have any additional questions or concerns.

goojoob commented 1 week ago

Thanks for the answer @onevcat , that make sense now. I've checked the server rate limits and it says: Your application should identify itself to our servers via a unique user agent string in order to achieve the maximum number of requests per minute. I guess i'll configure the user-agent in ImageDownloader to get the maximum quota.