1

I'm trying to fetch some data from coreData and display it in collectionView. Pretty basic. I do this on a background thread and then call reloadData on the main, as seen in the images.

But the problem is that sometimes it works and sometimes it doesn't, giving me index out of range. And I observed that when it crashes it enters some delegate method of collection view and not viewWillAppear

How I call it from ViewWillAppear Fetching data

Edit: Here Is the code

ALex
  • 673
  • 1
  • 6
  • 19

3 Answers3

1

You may have more than one problem. But, the first one would be that you didnt initialise the data containers. The collectionView delegate methods will be called before viewWillAppear. Try to intialise the containers in the viewDidLoad:

thumbnailsForSections = [String:[Thumbnails]]()
hasan
  • 23,815
  • 10
  • 63
  • 101
  • If it worked several times, why would it be from this ? I initialise it when I ise the GetData function which should be called everytime i enter the controller before the delegate methods. But as people said above it's something with concurency. I appreciate the help though – ALex Feb 13 '17 at 13:11
  • @user3018285 since the crash happened before the willViewAppear. its for sure you have a problem with initialisation and delegate get called before viewWillAppear. As I also said you may have more than one problem. This is one of them. Solve this first before you go forward. – hasan Feb 13 '17 at 13:15
0

Core data is not thread safe. You cannot store NSManagedObjects that were retrieved from a background thread and use them in the main thread.

Consider doing the fetch on the main thread or using a NSFetchedResultsController. This should not under normal circumstance take a long time even for a large amount of data. If this is taking a long time take a closer look at you data model or your predicate.

If want to continue using a background thread then you have to copy the values stored in NSManagedObject into a different thread-safe object (ie a custom NSObject subclass or a dictionary).

Jon Rose
  • 8,373
  • 1
  • 30
  • 36
  • Could you point me to some documentation or example? I'm pretty sure that if i try this by myself i'm gonna mess it up :) – ALex Feb 13 '17 at 13:12
  • You can read apple's doc on fetched results controller - they have a good walkthrough - https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/nsfetchedresultscontroller.html. – Jon Rose Feb 13 '17 at 14:39
  • It also looks like you have an issue that you are storing images in core data - this is generally a bad idea as it will load all of the data for all of image into memory when you do the fetch. What you can do is store the data as a relationship in a separate entity (which won't be loaded until you access it) and click 'allow external storage' so the data is in separate files not the sql file. See http://stackoverflow.com/questions/16685812/how-to-store-an-image-in-core-data – Jon Rose Feb 13 '17 at 14:40
  • I know about that but I also read that keeping small data it's ok, that's why i created thumbnails which are very small. I retrieve them and based on the date they were created i search for the big image when i push the next viewController when a cell is selected. As for fetched result controller, I don't have enough experience with it(actually none) and i think i will be a little lost in it. – ALex Feb 13 '17 at 15:52
  • I have one think to ask you though. When i retrieve the thumbnails, the memory that my app uses is increasing, normally. But why isn't it decreasing when i pop the controller? And by the way as it is now when i retrieve the thumbnails it uses around 140mb. Is it too much ? – ALex Feb 13 '17 at 16:02
  • `NSManagedObject` and `NSManagedContext` are not thread-safe, neither for reading or writing. You must use different contexts for different threads. Core-data can be setup to create background context that can be used on a background thread, but the context and the managed objects of that context must not leave that thread. – Jon Rose Feb 14 '17 at 11:40
0

Guys thank you for your trouble but i managed to obtain what i wanted.

I didn't solve the background issue instead i eliminated it. All i wanted to obtain was an activity indicator playing while the data was loaded from CoreData.

And by eliminating the queues it worked, which is pretty logical now that i think because i start the animation on the main thread and stop it after the whole data was loaded. So it seems the main thread "can do 2 things at the same time" ? :)

ALex
  • 673
  • 1
  • 6
  • 19