Core Data memory usage and Memory Warning

前端 未结 2 670
时光取名叫无心
时光取名叫无心 2020-12-25 08:30

I have this issue. I have a database of images in Core Data. I fetch all images (about 80MB) and put in an NSMutableArray. The objects are correctly faulted:



        
相关标签:
2条回答
  • 2020-12-25 09:23

    I think you should load the less objects into memory in batch.

    memory released by coredata happens behind the scenes and you don't have to program for it; the bad news is that it happens behind the scenes and thus can 'magically' chew up memory.

    Ways around it are many; for example, use a predicate to only select the rows you absolutely must need; don't do a general call to fetch everything and then go through the list one by one. More than likely you will crash when you do the general call and CoreData attempts to load all objects.

    0 讨论(0)
  • 2020-12-25 09:25

    Ok, I've understood why it happens. When you make a fetch request for an entity, even if the faulting is enabled, ALL DATA of that entity are loaded into memory. Including big binary data. You can solve this using many methods:

    1- setting this on your NSFetchRequest: [request setIncludesPropertyValues:NO]; setting NO, the data are not loaded into the cache immediately, but only upon request (when you access the property and the fault is fired) But this have a "problem". Even if you try to fault again the propery (because you don't need it immediately and want to free the memory, using [self.managedObjectContext refreshObject:object mergeChanges:NO];), the memory is not freed. The cache stay alive until the managedObjectContext is reset.

    This is better:

    2- you can split your data into separate entities. In my case I had only 2 properties: an url and image data. I splitted the data into 2 entities with a 1:1 relationship: imagecache and imagedata. Made a fetchRequest for all the row of the "imagecache" entity (with the url property), and like the previous solution no memory was cached. The propery imagecache.relationship.image was correctly faulted. Accessing this property caused the fault to fire and the cache to be filled. But in this case, doing [self.managedObjectContext refreshObject:object mergeChanges:NO]; on the "imagecache" object (the "father" object), resulted in immediately freeing the cache and the memory, faulting again imagecache.relationship.image property. Attention: Don't do on the "child" object, if you do [self.managedObjectContext refreshObject:object.relationship mergeChanges:NO], for some reason the cache is not freed. I think this is why you traverse the relationship.

    3- I said this was mainly an academic question, the real "all day" solution (better performance and less headache) for this issues is to avoid saving big data inside core data database. You can save your data as files and store only a reference (filepath) or, with iOS 5 you have the possibility to set "use external storage" on any "Data" property inside your core data model. This will do all the work for you.

    0 讨论(0)
提交回复
热议问题