Reading Core Data as Objects - ios

I have 1 entity in my database "Message" with the values MessageID, messageText and i want to read every row of Core Data, make an object of my class "Message" and put the new object into an array.
It's the first time I'm using Core Data and I don't quite get it yet, how I manage to do that.

Create a fetch request for the entity you wish to retrieve. Don't give it a predicate, set whatever sort descriptor you want.
Execute the fetch request in a managed object context and it will return an array of all the objects of that entity.
This is purposely just a descriptive answer, you can find the specifics of how to do this from the Core Data introductory documentation; you are new in Core Data and this is a good way to learn it.
Also - don't think of Core Data in terms of rows of data that you turn into objects. It's an Object-Relationship graph. It stores the objects of entities and their relationships between them. You don't turn the "rows" into objects, you get the objects back directly.

The response of #Abizern with code :
NSManagedObjectContext *moc = // your managed object context;
NSEntityDescription *entityDescription = [NSEntityDescription
entityForName:#"Message" inManagedObjectContext:moc];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
// You can also add a predicate or sort descriptor to your request
NSError *error;
NSArray *array = [moc executeFetchRequest:request error:&error];
if (array == nil)
{
// Deal with error...
}

Related

How do I get the actual property values of my model from Core Data?

I am trying to get all objects for an entity. I execute an NSFetchRequest and the objects are returned successfully in "fault" format. My question is, how can I take it a step further and access the actual object properties in my fetch result? This seems like it should be simple, yet I am missing something. Specifically, how I do get the values out of "result" below. I have tried iterating through result, assigning the current object to an NSDictionary, then accessing the object properties via objectForKey, but that did not work. I have read through apple developer documentation, online forums, stack overflow questions with no luck. Please help! I can save data to the database. BUT How do you get the freakin data OUT of the database using core data!!??
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *fetchReq = [[NSFetchRequest alloc] initWithEntityName:#"MyEntity"];
NSError *error = nil;
NSArray *result = [context executeFetchRequest:fetchReq error:&error];
By default objects will return as faults but as soon as you access any data it should work. For instance, if your MyEntity has a value called "name" you should be able to do
for (MyEntity *myEntity in result) {
NSLog(#"My entity name: %#", myEntity.name);
}
and you should get the results you expect.

Does Core Data persist the order of objects in NSMutableArray?

I basically operate on objects in a NSMutableArray, which is fetched from Core Data. All changes to those objects save in Core Data with the exception of the order of objects in the array. When, for instance, an object in the array is moved to the end of it, that does not seem to save in Core Data. Is it the case that Core Data does not persist order of objects in arrays? If so, what can be done to work around it? Sorting?
This is how I fetch data:
NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Item" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
self.items = [[managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];
And this is how I save changes:
- (void)saveCoreData{
NSManagedObjectContext *context = [self managedObjectContext];
NSError *error;
if (![context save:&error]) {
NSLog(#"Could not save data: %#", [error localizedDescription]);
}
}
If you're saving the array in a transform able property on an entity then the order will be saved - if you set the array back onto the managed object instance.
If the array is a fetched list of managed object instances then the order of that array means nothing and won't be saved. If you want to save this order then you need to add (and update) some other data in the context. This could be an order attribute on the entity or another entity with an ordered relationship perhaps.
If you're not using ordered relationships, then there is no guarantee of the order.
You can either set your relationships to be ordered. In this case you will have to deal with NSOrderedSet and different accessory methods. This feature is available in iOS5 and later.
Here is a great article of Ash Furrow (great developer, had a privilege to meet him) that covers ordered relationships in Core Data.
On the other hand, you can order your data once you access it. In my case I had an NSArray property that, once accessed, would get all objects in NSSet and order them. The disadvantage of this approach is every time you add new NSManagedObject to a relationship, mentioned NSArray will become outdated and must be recreated.

How to change value of an attribute of all entities in Core Data at once?

I am building application that has 'checklist' functionality. The checklist item is stored as Core Data entity. There is a 'checked' attribute stored as BOOL in the Datamodel as well. The view controller handling this checklist functionality is based on UITableViewController.
Basically, I would like to implement the UIRefreshControl which allow users to reset the 'checked' status of all checklist entities in Core Data. For example, all the items would be reseted and shown as 'unchecked' once user pulls down the UITableView.
However, NSFetchedResultsController only provides access to one entity at a time via [fetchedResultsController objectAtIndexPath:indexPath]. Would there be a way to get the whole collection of entities from Core Data as NSArray or NSDictionary therefore I could enumerate all entities and change their 'checked' attribute?
Agrees with coverback...lets say you want to fetch all the objects from the entity named "Test":
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Test"
inManagedObjectContext:context];
NSError *error;
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
fetchObjects array contains all the objects in "Test" entity
[fetchedResultsController fetchedObjects] will do just fine for your task.
In this case it is also not needed to use NSFetchedResultsController, you can get away with a simple NSFetchRequest.
I needed to update a lot of entities so the solution using NSFetchRequest were too slow. Luckily Apple added NSBatchUpdateRequest in iOS 8. Here's a simple example:
NSBatchUpdateRequest *batchUpdate = [[NSBatchUpdateRequest alloc] initWithEntityName:#"EntityName"];
batchUpdate.propertiesToUpdate = #{ #"attribute": #(0) };
batchUpdate.resultType = NSBatchDeleteResultTypeStatusOnly;
[managedObjectContext executeRequest:batchUpdate error:nil];
And here's a good blog post on the subject: https://www.bignerdranch.com/blog/new-in-core-data-and-ios-8-batch-updating/.

iOS Core Data unique object fetch

I'm fairly new to iOS/Cocoa and I have a very fundamental question about core data. I was looking over the internet to find a appropriate answer/solution but I wasn't able to.
So the question is how do you handle uniqueness in core data? I know that core data is not a database, its something like an object graph. Lets assume we have an entity called 'User' with the attributes 'id' and 'name' and a few relations to the other entities. Now we want to update the name of a specific user (e.g. a web service gave us the id and the new name).
This was the way I have done that before:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"User" inManagedObjectContext:context]];
[request setPredicate:[NSPredicate predicateWithFormat:#"id == %#", anId]];
NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
User *user = [results lastObject];
But than I've heard this is bad practice. Is it because fetch requests with predicates are very slow? I can't imagine that this is such a big deal. As far as I know there is no other way to get a unique object rather than go over each object and checking for equality..
Would it be more efficient to fetch all objects of the entity, put them in an array and looping through it manually (instead of the fetch request)?
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"User" inManagedObjectContext:context]];
NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
User *resultUser;
for(User *user in results){
if([user.id isEqual:anId]) resultUser = user;
}
Please help me finding the right path and thanks.
If you have an index for the property that you're fetching (there's a checkbox in the model editor), it's definitely a lot more efficient to use an equality predicate for fetching. Actually, it's never more efficient to fetch all objects and iterate over them in memory, but an index makes the difference more significant.
You're not fetching a unique object but rather objects containing a notionally unique atrribute value.
All managed objects are unique instances but nothing in Core Data enforces that the attribute values are unique. You could in principle have an arbitrary number of unique managed objects all which had identical attribute values. Only relationships enforce a unique position in the object-graph.
There's no particular reason not to fetch a particular object that contains a particular value if that is what your app requires.
I think what you've read is warnings against trying to cram SQL-like key values into entities and then to try and link managed objects together with those keys using predicates, for example doing something like:
EntityOne{
sqlKey:string
}
EntityTwo{
sqlKey:string
}
… and then trying to relate objects of the two entities with predicates.
(anEntityOneObject.)sqlKey == anEntityTwoObject.sqlKey
… instead of just setting a relationship in the data model.
EntityOne{
two<-->EntityTwo.entityOne
}
EntityTwo{
one<-->EntityOne.two
}
… and just finding the related objects with AnEntityOneObj.two.

Can I use NSFetchedResultsController for the display of data not meant for a UITableView?

In the FRC documentation, it says that it is intended to efficiently manage the results returned from a Core Data fetch request to provide data for a UITableView object.
I am trying to setup my Core Data stack to handle the storage and retrieval of some VERY basic data. Can I not use FRC? I need to display a value set in the db to a UILabel, what is the best Core Data method to use for that?
I have a core data book I am trying to get through, but the going is rough, so any help here would go a long way. Thanks!!
NSFetchedResultsController may be overkill if all you want is to fetch an object and display one of its attributes in UILabel. Take a look at NSFetchRequest and start with something like this:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:entityDescription
inManagedObjectContext:managedObjectContext]];
NSPredicate *predicate = /* define predicate here */;
[fetchReqest setPredicate:predicate];
NSError *error = nil;
NSArray *results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
If you want to sort your results, read up on NSSortDescriptor. You will need to set sort descriptors prior to -executeFetchRequest: call.
Your results will be in 'results' array - and they should include NSManagedObjects that you can get attribute values from.

Resources