Get array of objects from core data - ios

I am trying to adapt a method I was using to get a dictionary of ids from a core data request to an array of objects. However, I am getting confused about what array is the one I want. Basically, I want an array of contacts with all the appropriate attributes. Which array of contact objects in the following is the one I want, the fetchedObject or the tmpArray?
-(NSMutableArray *) getContactsNeedingSync
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSManagedObjectContext *context = [IDModel sharedInstance].managedObjectContext;
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"needsync==#1"];
fetchRequest.predicate = predicate;
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Contacts" inManagedObjectContext:context];
fetchRequest.entity = entity;
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"cid" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
fetchRequest.sortDescriptors = sortDescriptors;
NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
NSError *error = nil;
if (![fetchedResultsController performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
NSArray *fetchedObjects = fetchedResultsController.fetchedObjects;
//is this the array I want?
NSInteger resultCount = [fetchedObjects count];
if (resultCount == 0) {
NSLog(#"result Count is zero");
return [NSMutableArray array];//nothing in the Core Data store
}
else {
Contacts *contact;
NSMutableArray *tmpArray = [NSMutableArray array];
int i;
for (i = 0; i < resultCount; i++) {
contact = fetchedObjects[i];
tmpArray[contact.cid] = contact;
}
return tmpArray;//is this array I want?
}
context = nil;
}

Your code creates a fetch request and sets it up to collect a sorted set of objects. You then use an NSFetchedResultsController to collect the results for the fetch request. You then have a bit of code which resorts the sorted data (init tmpArray).
You can simplify this by removing the NSFetchedResultsController and just executing the fetch request directly. The NSFetchedResultsController isn't helping you as you aren't adding a delegate to it or retaining it.
The data is also already sorted because of the NSSortDescriptor. Indeed, if it was't you'd get crashes as you'd be trying to insert into an array that wasn't big enough... So, remove tmpArray and the associated code.

Related

How to select from core data with multiple filters?

From what I have found online it seemed as if this would be the way to select from core data on multiple values. I want to get everything from exercises where machineName = var1 or machineName = var2... For whatever reason nothing is returned after I debug past the executeFetchRequest selector and equiptmentData is empty. Also I do not get any errors. Any help or suggestions is much appreciated and thanks in advance.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Exercises" inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];
NSMutableArray *predicates = [[NSMutableArray alloc] init];
for(int i = 0; i < [checked count]; i++)
{
if([[checked objectAtIndex:i] boolValue] == YES)
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"machineName == %#", itemArray[i]];
[predicates addObject: predicate];
}
}
NSArray *predicatesArray = [[NSArray alloc] initWithArray: predicates];
NSPredicate * compoundPredicate = [NSCompoundPredicate orPredicateWithSubpredicates: predicatesArray];
fetchRequest.predicate = compoundPredicate;
NSError *error = nil;
NSArray *equiptmentData = [managedObjectContext executeFetchRequest:fetchRequest error: &error];
Turns out this is the right way to do this I was not inserting into core data properly

Is there a faster way to retrieve a specific managedObject in Core Data than a fetch request?

I have a method to create managed objects (IntersectionObject) each with three properties. These three properties are managed objects themselves.
PropertyObject1, PropertyObject2, and PropertyObject3 each has about 20 different possibilities.
An IntersectionObject is essentially a combination of a particular PropertyObject1, PropertyObject2, and PropertyObject3.
There are about 1200 IntersectionObjects and to create them I am using a fetch request to retrieve and set the the correct PropertyObject:
- (PropertyObject1 *)fetchedPropertyObject1FromID: (NSNumber *)propertyObjectID {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"PropertyObject1" inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];
NSError *error = nil;
NSArray *fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
NSLog(#"error fetching PropertyObject from ID, error:%#", error);
return nil;
}
for (PropertyObject1 *object in fetchedObjects) {
if (object.propertyObjectID.longValue == propertyObjectID.longValue) {
return object;
}
}
return nil;
}
I am finding that repeating this fetch three times for each of the 1200 IntersectionObjects takes about 2 seconds, and is too slow. Is there a faster way to do this?
EDIT: the accepted answer has the solution that I used in the comments below it. It turns out simply mapping the PropertyObjects to a dictionary was the simplest and quickest way to get the associated objects.
If you have the managed object id, use objectWithID: on the MOC.
If you don't, and you're going to be creating a lot of associations in a short space of time, fetch all of the managed objects from the MOC in batches (perhaps 100 items each batch, see fetchBatchSize on NSFetchRequest), create a dictionary mapping your objectID to the managed objects so you can just do a local lookup. Turn each object back into a fault as you process the batch with refreshObject:mergeChanges:.
Use a predicate to do this, also set the fetch limit to 1. This should get your result in a much more optimized fashion:
- (PropertyObject1 *)fetchedPropertyObject1FromID: (NSNumber *)objectID {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"PropertyObject1" inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"objectID == %#", objectID]];
[fetchRequest setFetchLimit:1];
NSError *error = nil;
NSArray *fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
NSLog(#"error fetching PropertyObject from ID, error:%#", error);
return nil;
}
if(fetchedObjects.count > 0)
{
[return fetchedObjects objectAtIndex:0];
}
return nil;
}

how to edit coredata value then save context to overwrite old values?

I am trying to edit a item in one of my coredata tables/entities. I am not 100% sure how to do this but I think its along these lines.
First you create the context, then fetchrequest the entity using a predicate to select the exact item from the table/entity. then save these values into the correct var type update the values then some how overwrite the existing item with the new values.
The last part is where I am stuck, this is the code I currently have:
- (void)editSelectedInstall:(NSString *)invGuid {
NSManagedObjectContext *context = [self managedObjectContext];
if (context == nil) {
NSLog(#"Nil");
}
else {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Install" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"invGUID==%#",invGuid];
[fetchRequest setPredicate:predicate];
NSError *error = nil;
NSArray *myArray = [context executeFetchRequest:fetchRequest error:&error];
NSMutableDictionary *myDictionary = [myArray objectAtIndex:0];
NSLog(#"%#", myDictionary);
// Here I will update the values & then save the context?
// For example I think I am to update the items like this:
myDictionary.num = #"1234";
myDictionary.name = #"new name";
}
}
I think I'm almost there I just need help saving the context so that it overwrites the previous values.
Try this:
//loop through result set and update as required
for (Install *temp in myArray) {
temp.num = #"1234";
temp.name = #"New name";
}
//save
[context save:&error];

How to read NSArray from coredata entity

I am trying to read a coredata entity into a NSMutableArray however I keep getting back weird lots of data. For instance when I get back an NSDictionary of values it looks like this
data: {
companyName = "WPremium";
desc = "Test";
guid = "Otq12342";
install = (
"0x1e59e910 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p851>",
"0x1e59e8e0 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p848>",
"0x1e59e830 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p837>",
"0x1e59e930 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p853>",
"0x1e59e850 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p839>",
"0x1e59e890 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p843>",
"0x1e59e8b0 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p845>",
"0x1e59e7c0 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p830>",
"0x1e5957e0 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p829>",
"0x1e59e810 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p835>",
"(...and 16 more...)"
);
I would like to know how to put the install object of the coredata dictionary into an NSArray so I can sort it.
Update: this is how I call my coredata object.
- (NSMutableArray *)readSelectedInstall:(NSString *)projIDString {
NSManagedObjectContext *context = [self managedObjectContext];
if (context == nil) {
NSLog(#"Nil");
}
else {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"InstallProject" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"projID==%#",projIDString];
[fetchRequest setPredicate:predicate];
NSError *error;
NSMutableArray *installProjectDictionaryArray = [[NSMutableArray alloc] init];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
for (InstallProject *installProj in fetchedObjects) {
NSMutableDictionary *tempInstallProjectDictionaryArray = [[ NSMutableDictionary alloc] init];
[tempInstallProjectDictionaryArray setObject:installProj.companyName forKey:#"CompanyName"];
[tempInstallProjectDictionaryArray setObject:installProj.projNo forKey:#"ProjNo"];
[tempInstallProjectDictionaryArray setObject:installProj.desc forKey:#"Desc"];
[tempInstallProjectDictionaryArray setObject:installProj.guid forKey:#"GUID"];
[tempInstallProjectDictionaryArray setObject:installProj.projID forKey:#"ProjID"];
[tempInstallProjectDictionaryArray setObject:installProj.install forKey:#"install"];
[installProjectDictionaryArray addObject:tempInstallProjectDictionaryArray];
}
return installProjectDictionaryArray;
}
return nil;
}
then with the returning NSMutableArray I do this
NSMutableArray *getarray = [self readSelectedInstall:projIDString];
NSMutableDictionary *installsDictionary = [getarray objectAtIndex:0];
NSMutableArray *tempInstalls = [installsDictionary objectForKey:#"install"];
NSLog(#"%#", tempInstalls);
NSArray *tempSortedItemsArray = [tempInstalls sortedArrayUsingDescriptors:
#[[NSSortDescriptor
sortDescriptorWithKey:#"dp" ascending:YES],
[NSSortDescriptor
sortDescriptorWithKey:#"dc
" ascending:YES]]];
tempInstalls = [tempSortedItemsArray mutableCopy];
tempSortedItemsArray = nil;
NSLog(#"%#", tempInstalls);
but on that last line of code is where I have the weird output.
All you need to do is fetch the core data NSManagedObject from Core Data, install would be returned as an NSSet, by the looks of things it is an NSSet of NSManagedObjects.
Once you have the object you access the "install" property and sort however you want.
// Get the Core Data Object (Uses Magical Record)
MyObject *object = [MyObject MR_findFirstWithPredicate:[NSPredicate objectPredicate:self.users_id]];
// Sort the object set into an array
NSArray *installs = [object.install sortedArrayUsingDescriptors:#[ [NSSortDescriptor sortDescriptorWithKey:k_timestamp ascending:YES] ]];

fetching specific data from core data database and displaying in UITableView

I currently have a table view that displays all the contents of the database Entity: ExData.
ExData has an attribute tag of string type.
What my problem is that i would like to display the contents of the ExData in the table view but only the entries that have a tag set of 2 for example.
The tag is to be sent from the previous view controller but this can be sorted out later as firstly i would just like to hard code only one tag value entries being displayed
ExDatasArray is a mutable Array.
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"ExData"];
self.ExdatasArray = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
Above is how the data from ExData is being fetched...
To fetch specific data, you add a predicate to the fetch request:
NSString *theTag = ...
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"tag == %#", theTag];
[fetchRequest setPredicate:predicate];
Remark: If you are displaying the result set in a table view, you might also consider to
use a NSFetchedResultsController.
If I understand your question correctly, you are trying to limit the results of the fetchRequest. Use an NSPredicate to specify the query and if desired an NSSortDescriptor to sort it. Below I assume that your tag attribute is named tag, and that searchTagValue has been set appropriately.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"ExData"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"tag == %#", searchTagValue];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"tag" ascending:YES]];
NSError *error;
NSArray *results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (!result) {
// handle error
}
else {
self.ExdatasArray = [results mutableCopy];
}

Resources