kolinkrewinkel / KKGridView

Deprecated: Grid view library for iOS.
https://github.com/kolinkrewinkel/KKGridView
Other
821 stars 151 forks source link

Need to reload cells after memory runs out #137

Open jonsterling opened 12 years ago

jonsterling commented 12 years ago

This may be a problem with the demo, or with the library (I haven't looked very far into it). But when the device runs out of memory, all the cells go blank. We need to start reloading them or something…

TomWol commented 12 years ago

I am experiencing this aswell, though in my case it's not always all cells that go blank. Sometimes, the last cell stays normal, while the rest turn blank. Dunno if that might aid in finding the cause, just thought I'd mention it. I'm using a slightly edited version of the demo, latest commit.

chrhansen commented 12 years ago

I got the exact same issue as TomWol, either all blank or just, say, the first half.

TomWol commented 12 years ago

Would you consider pointing me into the direction where this bug might possibly be located, jonsterling? You definitely know the code better than I do and I need all the help I can get; I'm using this code for a project at my university and I'd like to get the issue resolved before I send in my project. Thanks!

kolinkrewinkel commented 12 years ago

Try calling reloadCells by subscribing to the DidReceiveMemoryWarning notification.

TomWol commented 12 years ago

Thanks for responding! I tried subscribing to the didReceiveMemoryWarning notification, but when I got the blank cells I did not receive any notification on memory. However, since I was running the app in the iOS Simulator, I generated a memory warning through the menu, which did trigger a notification and also resulted in some of the cells going blank. I put

[super didReceiveMemoryWarning];
[self.gridView reloadData];

in the didReceiveMemoryWarning function in my GridViewDemoViewController, but that didn't change anything. The method definitely got called when I simulated the warning, as I set a breakpoint. Any further ideas?

kolinkrewinkel commented 12 years ago

Perhaps modifying KKGridView to include a listener for the notification itself would fix it, using an internal _reloadCells method (I forgot the naming exactly, but I think you get the gist.)

On Aug 9, 2012, at 6:57 PM, TomWol notifications@github.com wrote:

Thanks for responding! I tried subscribing to the didReceiveMemoryWarning notification, but when I got the blank cells I did not receive any notification on memory. However, since I was running the app in the iOS Simulator, I generated a memory warning through the menu, which did trigger a notification and also resulted in some of the cells going blank. I put

[super didReceiveMemoryWarning]; [self.gridView reloadData]; in the didReceiveMemoryWarning function in my GridViewDemoViewController, but that didn't change anything. The method definitely got called when I simulated the warning, as I set a breakpoint. Any further ideas?

— Reply to this email directly or view it on GitHub.

TomWol commented 12 years ago

I've been looking into this, what I've come to is this:

Both Christian-Hansen and myself noticed that pretty much always, when cells go blank it's the first ones or more that go blank. Usually there are a few cells at the end that stay loaded. I found out that the cache system used in GridViewDemoViewController started returning null files for keys that had images stored in the initialization. So I started looking into NSCache, which is essentially a blackbox unfortunately. As stated on the Apple developer reference:

The NSCache class incorporates various auto-removal policies, which ensure that it does not use too much of the system’s memory. The system automatically carries out these policies if memory is needed by other applications. When invoked, these policies remove some items from the cache, minimizing its memory footprint.

I also found the following bit online when looking further into NSCache, which states:

NSCache also doesn't flush everything when memory is tight, just as many objects as necessary.

This would explain why the last items usually remain. Its flush (or eviction as it's officially called) goes from front to back.

I then re-read what I posted before: the cells will go blank without an observer noticing a memory warning, but also when there is a memory warning. The lack of an actual memory warning (also resulting in an eviction) hints at the fact that NSCache evicts items even before a memory warning is issued, if possible. This makes sense, it doesn't want to respond to a memory warning, but rather avoid one. This is why my observers wouldn't indicate a memory warning when the cells went blank.

So removing the caching principle from GridViewDemoViewController seems to be a way to fix this issue. You can easily replace it with an NSDictionary and keep most of the caching code. Issuing a memory warning keeps the cell images right where they should be in that case. If you're desperate for a fix, that's all you need to do. The problem with using NSCache is that any content that you put into it will be evicted at a point which, as far as I can tell cannot be detected. So I don't know how else to fix this than to not use the caching.