Kingfisher: Crash at `ImageCache.travelCachedFiles(onlyForCacheSize : Bool) -> (urlsToDelete : [URL], diskCacheSize : UInt, cachedFiles : [URL : URLResourceValues])`

Created on 9 Mar 2017  ·  8Comments  ·  Source: onevcat/Kingfisher

An crash occurred when called kf.setImage(with:placeholder:options:progressBlock:completionHandler:) to UIImageView immediately after opened the app from background.

Fatal Exception: NSInvalidArgumentException
0  CoreFoundation                 0x19144efb8 (Missing)
1  libobjc.A.dylib                0x18feb0538 (Missing)
2  CoreFoundation                 0x191455ef4 (Missing)
3  CoreFoundation                 0x191452f44 (Missing)
4  CoreFoundation                 0x19134ed0c (Missing)
5  Kingfisher                     0x101b062b4 ImageCache.travelCachedFiles(onlyForCacheSize : Bool) -> (urlsToDelete : [URL], diskCacheSize : UInt, cachedFiles : [URL : URLResourceValues]) (ImageCache.swift:485)
6  Kingfisher                     0x101b14d5c specialized ImageCache.(cleanExpiredDiskCache(completion : () -> ()?) -> ()).(closure #1) (ImageCache.swift:420)
7  Kingfisher                     0x101b13614 partial apply for ImageCache.(cleanExpiredDiskCache(completion : () -> ()?) -> ()).(closure #1) (ImageCache.swift)
8  libdispatch.dylib              0x1903069e0 (Missing)
9  libdispatch.dylib              0x1903069a0 (Missing)
10 libdispatch.dylib              0x190314ad4 (Missing)

This is Fabric Crashlytics report:

screen shot 2017-03-09 at 13 14 31

When debug mode, I saw the image view flickering a little(reproduced on the sample project), and I archived(release mode) and publish via Fabric, it crashes.

My code is so simple:

screen shot 2017-03-09 at 13 21 48

I suspect https://github.com/onevcat/Kingfisher/issues/86 is related.


version: 3.5.1 (current latest)

Most helpful comment

Ah,

I could reproduce it! You need to click the reload button really quite fast.
Currently have no idea on it, but I will investigate it more on it.

Before we could get conclusion, we could leave this issue open for a while.

All 8 comments

The crash is fixed by this commit: https://github.com/gram30/Kingfisher/commit/d222bf4eaae3b045bff4c79e6033c36399697f05
(Of course, this isn't desirable solution.)

The crash occurred in background task( and I saw the crash if open the app immediately after closed).
(The crash occurred only archived/release build.)

I saw the image view flickering a little(reproduced on the sample project)

And this flickering remains :(
You can reproduce flickering by this:

  1. Launch iOS sample app
  2. Close the app (not terminate, just close to be background)
  3. Open the app
  4. Tap Reload button immediately after the app became foreground
  5. Image view is flickering

    • If Reload button tapped a few seconds after became foreground, not flickering occurred.

I fixed the crash by https://github.com/onevcat/Kingfisher/pull/620
Is it okay?

I saw the image view flickering a little(reproduced on the sample project)

I think this is different problem, and I have no solution yet.

@mono0926
Thanks for your fix on crash. I will take a look at it later.

For the flickering, it is intended since Kingfisher will clean the memory cache when you switch to background. When you reload the images after that, the images will be retrieved from disk, which is an async operation (to keep best UI performance). The image views will be set to placeholder as soon as you call set method, but the final images will be set after a few run loops. It is the reason for the flickering if you are using something like nil as placeholder.

You could add .keepCurrentImageWhileLoading option to keep the loaded images so it could be avoided. However, this flickering should always happen when after you switching background, I wonder why you say "If Reload button tapped a few seconds after became foreground, not flickering occurred".

@onevcat

Thank you, I've figured out the flicking :)

I'm happy that the crash resolved.
(I re-archived my app using Kingfisher built from master branch, and no crash occured.)

So, I think this issue can be closed 😄

I added . keepCurrentImageWhileLoading option, but flickering occurred still, and it is reproduced on the sample app…
This code seems to be correct, so I don't know why the flickering isn't resolved.

However, this flickering should always happen when after you switching background, I wonder why you say "If Reload button tapped a few seconds after became foreground, not flickering occurred".

I don't why, but it seems to me that the flickering likely to occur under that condition 🤔
(I suspect that, after launched, a few process run, so UI refreshing is relatively slow.)

:(
I cannot reproduce the flickering after I added .keepCurrentImageWhileLoading in the sample app. So I guess it might be some other issues. Which systems/devices did you try? Did you change anything else in the sample app?

@onevcat

I modified only this line:

ViewController.swift#L73

- options: [.transition(ImageTransition.fade(1))],
+ options: [.transition(ImageTransition.fade(1)), .keepCurrentImageWhileLoading],

Condition:

  • Xcode 8.2.1
  • iPhone 7 (iOS 10.2) Simulator

    • iPhone 7 Plus (iOS 10.3 beta) Device, also (modified only signing setting to execute)

If I noticed the cause I'll report, thanks 😃

Ah,

I could reproduce it! You need to click the reload button really quite fast.
Currently have no idea on it, but I will investigate it more on it.

Before we could get conclusion, we could leave this issue open for a while.

In Kingfisher 5, we have a better way to prevent any of the flickerings in the table view or collection view. Use loadDiskFileSynchronously to solve it and avoid side effects in cell reusing.

Was this page helpful?
0 / 5 - 0 ratings