iOS - Reorder Items in CoreData - ios

I have a tableView and an array locationsArray. The locations array is filled on viewDidLoad from data in my CoreData.
I have implemented the reorder methods on the tableView and that works fine however I can't figure out how to save the reordered array back into CoreData. I've tried deleting everything in CoreData and just saving the new reorderedArray. Although this is obviously very costly resource wise it seems to just load the elements back into the array in a seemingly random order.
Is there an easy way to do this that I am missing or can you not store things in CoreData in a certain order?

Strictly saying, it is impossible to store objects in certain order. You can only set the order for retrieved objects
When you retrieve locationsArray from CoreData, you have no any guaranties about their order.
The only way - add field to your Managed Object that will be used to order your locations.
Than, on retrieval, you'll be able to use locationsArray = [locationsArray sortedArrayUsing<#WhateverYouNeed#>];.
You can, also, achieve this by using sortDescriptors property of NSFetchRequest. It will provide you with desired behaviour from the box. The only downside of it, that your NSSortDescriptor in that case cannot be defined by block, so if you ordering is using some complex approach, you'll need to sort the result with already fetched data

use the predicate to sort the array or after fetching the array from coredata sort it using
NSArray *sortedlocationarray = [filteredlocationarray sortedArrayUsingDescriptors:#[sortDescriptor]];
where filteredlocationarray is from coredata.

Related

NSFetchRequest based on array property size

I have a NSManagedObject which has a (transformable) NSArray property arrayProperty.
I would like to execute a fetch request filtering for objects whose property size is less than 5. I tried
[NSPredicate predicateWithFormat:#"arrayProperty.#count <= 5"]
and
[NSPredicate predicateWithFormat:#"arrayProperty[SIZE] <= 5"]
but none of them work (giving Unsupported function expression count and Unsupported function [SIZE]).
Is there a way to achieve this?
This kind of thing isn't possible with transformable properties. Transformable are convenient for storing data, but once they're stored, that's all they are-- a bunch of bytes with no information about the data structure that created them. SQLite doesn't know that it's an array, so it's not able to do things like count how many items are in the array.
If you use transformable properties, you lose any ability to filter based on them, except for extremely basic tests like whether the value is nil.
If you need to do this kind of filtering, you'll need to consider how to change your data model. One possibility would be that instead of saving an array, create a new entity with a to-many relationship to store the values.

CoreData doesn't keep the sequence while saveContext

I am trying to insert data in CoreData. I have may records to insert, this should be all or none. So I am creating instance of NSManagedObject and inserting it to NSManagedObjectContext one by one.
When I call below method after inserting all records:
[_myManagedObjectContext saveContext:&error];
This method save all inserted records to persistent store. When I open the Sqlite file generated by core data, I found all the records inserted by my app.
Problem is the order is not same. e.g I inserted records based on serial number 1-100 in sequense, I am able to see random sequence in CoreData sqlite file.
I know that I should not worry about the entries on core data sqlite file I can always fetch records in sorted order using NSPredicate but I need to keep the sequence because in some circumstances I need to study the database file.
Can someone tell me what to do to let saveContext method save records in the same order those are inserted to context?
The only way to reliably maintain order of your objects is to add an additional attribute on the object, such as 'index', and then set the value once the object has been created. Use this object to sort the results when you retrieve them or use the index to retrieve the objects in the required order.
The easiest way is to implement the NSManagedObject subclass's awakeFromInsert method and set a date property to NSDate(). Now you have a sequence which is accurate to 10,000th of a second. When you need items in order, just sort by this date property.

Should I use an [NSManagedObject] as the data for a UITableView?

Here's the scenario that I'm interested in:
1) I'm using CoreData to store my data for my app
2) I'm using a UITableView to show that data to my user
My question is whether or not I should use an [NSManagedObject] as the data for the UITableView.
Obviously it will work just fine to do it this way, but a part of make feel like it's not best practice to do this. I could use a dictionary or an array or something else to store the data and then when it's time to save, I could save that array to CoreData.
Is there any reason that one of these approaches is better than the other?
You should almost certainly use NSManagedObjects as the data for your table view, if only to save yourself the hassle of transforming arrays and dictionaries into/from NSManagedObjects in order to save/load from CoreData.
If by [NSManagedObject] you mean an array of NSManagedObjects, that is certainly possible. But best practice when using CoreData with UITableViews is to use an NSFetchedResultsController. The two main advantages are:
Easy processing of table view sections. Specify a sectionNameKeyPath and corresponding sort descriptor, and the FRC will determine which section each object should appear in, assigning objects to indexPaths accordingly.
Automatic processing of insert/update/deletes. There is boilerplate code which will enable the FRC to update the table view whenever objects are added, amended or deleted.
One other advantage to using NSManagedObjects directly, rather than arrays and dictionaries, is memory management: NSManagedObjects are fetched as "faults" initially and their properties will be populated only as required, reducing memory requirement compared to arrays and dictionaries which would presumably have to be fully populated from the outset.

Core Data working with subset of full data store...HOW?

I'm banging my head trying to figure out something in Core Data that I think should be simple to do, and I need some help.
I have a data store which contains data from the past two years, but in my app, I have certain criteria so that the user only works with a subset of that data (i.e. just the past month). I have created the predicates to generate the fetch request and all that works fine.
My issue is that I then want to run some additional predicates on this subset of data (i.e. I just want objects with name=Sally). I'd like to do so without having to re-run the original predicate with an additional predicate (in a NSCompoundPredicate); I'd rather just run it on the subset of data already created.
Can I just run a predicate on the fetch results?
Is the format of the predicate the same as for the initial calls into the core data store?
Thanks for any help.
You could filter the original array of results using a predicate. See the NSArray filteredArrayUsingPredicate method.
The only reason I would consider doing what you're talking about is if you find that modifying the predicate at the FetchedResultsController level caused significant performance degradation.
My recommendation is to get a reference to your fetchedResultsController in your view controller and update your predicate with a compound predicate matching your additional search parameters.
If you were to tie your viewControllers data source to a predicate of a predicate you wouldn't be able to properly utilize the NSFetchedResultsControllers Delegate methods that allow for easy, dynamic updating of Views such as table view and collection view.
/* assuming you're abstracting your datastore with a singleton */
self.fetchedResultsController = [DataStore sharedStore].fetchedResultsController;
self.fetchedResultsController.delegate = self;
[self.fetchedResultsController.fetchRequest setPredicate:yourPredicate];
Make sure to configure your fetch requests' batch size to a reasonable value to improve performance.

CoreData sorted entities - performance

I would like to have my CoreData entities stored in a sorted array/set, so that I don't have to sort it every time in a fetch using NSSortDescriptor. In iOS 4 and below, I believe this is my only option, but sorting the entire data set (not just the fetched results) every time - that sounds terribly inefficient, even for a relatively small data set of ~10k.
In iOS 5 there are sorted sets; I wonder if the performance gain is enough to warrant dropping iOS 4 support? Any experiences to be shared?
You don't need to sort the results - you can do your fetch and pass sortOrderings to the fetch. If you need to traverse a relationship, you can add a method of your own on the parent that does a raw fetch on the child, has a predicate added where the parent relationship is self, add your own sort orderings and returns a nice NSArray :)
I mean hey, if you can force iOS5, great, but if you need to keep iOS 4 around, letting the database do the sorting is very performant.

Resources