I have look around for something similar with no luck so I am going to try and explain my trouble and paste some code. I have an application that uses Core Data and I can save and retrieve data from their respective textFields with the exception of my (to many relationships). I believe these are saved and returned as sets when fetched. I have read up on NSSet and looked at some code but with still do not understand how to code it.
Thanks for any help.
Hudson
- (IBAction) findContact
{
AppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Place"
inManagedObjectContext:context];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
[fetchRequest setEntity:entity];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"placeName = %#", placeName.text];
[fetchRequest setPredicate:pred];
Place *matches = nil;
NSError *error;
NSArray *objects = [context executeFetchRequest:fetchRequest error:&error];
if ([objects count] == 0) {
status.text = #"No matches";
}else{
matches = [objects objectAtIndex:0];
address.text = [matches valueForKey:#"address"];
city.text = [matches valueForKey:#"city"];
state.text = [matches valueForKey:#"state"];
zip.text = [matches valueForKey:#"zip"];
phone1.text = [matches valueForKey:#"phone1"];
email.text = [matches valueForKey:#"email"];
website.text = [matches valueForKey:#"website"];
phone2.text = [matches valueForKey:#"phone2"];
about.text = [matches valueForKey:#"about"];
photoName.text = [[matches photo]valueForKey:#"photoName"];
status.text = [NSString stringWithFormat:#"%d matches found", [objects count]];
NSSet *groupForSections = [groupForSections valueForKey:#"sections"];
for (Group *group in groupForSections) {
NSLog(#"group name = %#", [groupForSections valueForKey:#"groupName"]);
groupName.text = [group valueForKey:#"groupName"];
NSSet *sectionForPlaces = [sectionForPlaces valueForKey:#"places"];
for (Section *section in sectionForPlaces) {
sectionName.text = [section valueForKey:#"sectionName"];
NSLog(#"section name = %#", [section valueForKey:#"sectionName"]);
}
}
}
}
![enter image description here][1]
According to your follow-up comments, Place does not actually have a to-many relationship to Section, and Section does not actually have a to-many relationship to Group. Instead, Group has a to-many relationship (sections) with Section and section's inverse to-1 relationship is called group. Also, Section has a to-many relationship (places) with Place and Place's inverse to-1 relationship is called section.
If all those assumptions are correct (and without seeing your model it's hard to know if that is correct), your code should now be something like:
NSManagedObject *sectionForPlace = [matches valueForKey:#"section"];
sectionName.text = [sectionForPlace valueForKey:#"sectionName"];
NSManagedObject *groupForSection = [sectionForPlace valueForKey:#"group"];
gromName.text = [groupForSection valueForKey:#"groupName"];
This code doesn't directly access the fields through the NSManagedObject classes you've created, which should also work if you prefer that way.
Related
I want to store data from a text field. And then use this data to populate the text in a label inside a view controller. Is this possible? Ive messed around with it, but nothing seems to work. Any thoughts? Here are my two methods...
- (IBAction)saveButton:(id)sender {
CoreDataStack *coreDataStack = [CoreDataStack defaultStack];
NSManagedObject *noteEntry = [NSEntityDescription insertNewObjectForEntityForName:#"Notes" inManagedObjectContext:coreDataStack.managedObjectContext];
[noteEntry setValue:_notesField.text forKey:#"notes"];
NSError *error = nil;
// Save the object to persistent store
if (![coreDataStack.managedObjectContext save:&error]) {
NSLog(#"Can't Save! %# %#", error, [error localizedDescription]);
}
[coreDataStack saveContext];
}
Here is my view did load method:
- (void)viewDidLoad
{
[super viewDidLoad];
CoreDataStack *coreDataStack = [CoreDataStack defaultStack];
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:#"Notes"];
Notes *entry = [NSEntityDescription insertNewObjectForEntityForName:#"Notes" inManagedObjectContext:coreDataStack.managedObjectContext];
_outputLabel.text = entry.notes;
}
Your code in the saveButton: method seems OK. But your code in the viewDidLoad method seems wrong. Are you trying to do the following?
- (void)viewDidLoad {
[super viewDidLoad];
CoreDataStack *coreDataStack = [CoreDataStack defaultStack];
//First way to init your fetchRequest:
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:#"Notes"];
//Second way to init your fetchRequest:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Notes" inManagedObjectContext:coreDataStack];
[fetchRequest setEntity:entity];
//Having a NSEntityDescription object can be usefull if you need to group your data, for example
//Set some predicates, if necessary
//Set some sortdescriptors, if necessary
NSError *error;
NSArray *resultsArray = [coreDataStack executeFetchRequest:request error:&error];
NSLog(#"%#", resultsArray);
_outputLabel.text = [[resultsArray firstObject] notes]; //if your array can only have one object
}
The NSLog will give you the structure of your fetch array (I can't guess it). You will then be able to set _outputLabel.text.
Answer by #user1966109 is exactly correct answer what you are looking for. Since you need to show the text in a label and for that you need to set predicate to get a single row. Set the predicate as below
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"value == abc"];//considerin abc is the word you are looking for.
request.predicate = predicate;
//then execute the query.
I am actually new to iPhone programming and have successfully create an app but I can't figure out how to retrieve the values stored in NSSet. I have 2 entities in core data related to each other. Users one-to-many to Scores. Users entity has firsNname and lastName attributes and Scores entity has onTime, wasAbsent, and dateIn attributes. I fetch using predicate based on firstName and lastName and then execute the fetch. The fetch is successful and I am able to get both entities in one fetch call. However I cannot get values for the values from Scores entity. Whatever I do, it always returns NSSet object. What I want to do is to retrieve the boolean value which was stored in onTime and wasAbsent attributes and feed them to UISwitch.
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
self.managedObject = delegate.managedObjectContext;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Student"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"firstname == %# AND lastname == %#", #"James", #"Smith"];
NSError *error = nil;
self.scoresArray = [self.managedObject executeFetchRequest:fetchRequest error:&error];
if ([self.scoresArray count]) {
Student *student = [self.scoresArray objectAtIndex:0];
NSSet *score = student.scores;
NSArray *arr = [score allObjects];
NSLog(#"%#", [arr objectAtIndex:0]);
}
if I can directly access the Score entity instead of using NSSet, that would be ideal that way I can reference it using a dot notation.
Any help would be appreciated. Thanks
Use something like the following:
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
self.managedObjectContext = delegate.managedObjectContext;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Student"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"firstname == %# AND lastname == %#", #"James", #"Smith"];
NSError *error = nil;
NSArray *studentArray = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
for (Student *student in studentArray) {
Student *student = [self.studentArray objectAtIndex:0];
NSLog(#" student is %# %#", student.firstname, student.lastname);
for (Score *score in student.scores) {
// Do something with score
NSLog(#" score is %#", score);
}
}
Because Student has to-many relationship to Scores (and the property for it is scores), when you get the value of student.scores, it returns an unordered collection, which is NSSet in Foundation. So you just work with it like you work with NSSet and with collections in general.
I am really having trouble retrieving items that have been created through the Menu entity. This is the code I used to add an item to a specific Menu object
-(void)additem:(NSString *)entity :(NSDictionary *)aDictionary :(NSString *)menu
{
NSLog(#"additem");
NSError *error = nil;
Menu *menuItem = nil;
NSFetchRequest * request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"Menu" inManagedObjectContext:managedObjectContext]];
[request setPredicate:[NSPredicate predicateWithFormat:#"mname=%# and msection =%#",#"Parents",#"Keydates"]];
menuItem = [[managedObjectContext executeFetchRequest:request error:&error] lastObject];
if (error) {
//Handle any errors
}
if (!menuItem) {
//Nothing there to update
NSLog(#"This class doesn't exist");
}
Items *anitem = (Items *)[NSEntityDescription insertNewObjectForEntityForName:#"Items" inManagedObjectContext:managedObjectContext];;
anitem.type = [aDictionary objectForKey:#"type"];
anitem.title = [aDictionary objectForKey:#"title"];
anitem.image = [aDictionary objectForKey:#"image"];
anitem.subtitle = [aDictionary objectForKey:#"subtitle"];
[menuItem addItemsObject:anitem];
[managedObjectContext save:&error];
}
I want to use a predicate to retrieve all the items that were created on a specific Menu object. Here is the code I am trying to retrieve it with.
- (void) readItems: (NSString *)section {
NSLog(#"readItems");
NSError *error = nil;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Menu"
inManagedObjectContext:managedObjectContext];
fetchRequest.resultType = NSDictionaryResultType;
[fetchRequest setEntity:entity];
[fetchRequest setReturnsObjectsAsFaults:NO];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"mname=%# and msection = %#",#"Parents",#"Keydates"]];
NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
for (Items *item in fetchedObjects) {
NSLog(#">>>>>>%#",item);
}
}
Can anyone point me in the right direction.I know I pass section and don't use it. I have place the actual values in.
Your readItems: method specifies the entity for your fetch as Menu yet when you execute the fetch you are expecting Item (since you start iterating through fetchedObjects and casting them as Item).
Instead what you want to do is et your entity to Item and change the predicate to
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"items.mname=%# and items.msection = %#",#"Parents",#"Keydates"]];
Furthermore you should consider renaming your relationships. The relationship field specifies exactly what you would expect to see when you follow the arrow. Thus when I look at Items and follow its arrow to Menu I would expect the name of this relationship to be menu yet you call it menuItems. You have done this correctly for the relationship from Menu to Item.
That way we would end up with a more readable predicate looking like:
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"menu.mname=%# and menu.msection = %#",#"Parents",#"Keydates"]];
Happy Coding
I have two Entities in my CoreData model, "Valla" and "Dagbok", these are related with a many-to-many relationship.
When i add a new post to the Dagbok-entity i want it to relate to posts from Valla-entity that i store in an NSArray from a FetchRequest.
The code right now just adds a post to Dagbok
- (void)initDagbokDBWithText:(NSString *)text header:(NSString *)header degree:(int)degree weather:(NSString *)weather farg:(NSString *)farg
{
AppDelegate *appdelegate = [[UIApplication sharedApplication]delegate];
context = [appdelegate managedObjectContext];
NSEntityDescription *entitydesc = [NSEntityDescription entityForName:#"Dagbok" inManagedObjectContext:context];
NSManagedObject *newDagbok = [[NSManagedObject alloc] initWithEntity:entitydesc insertIntoManagedObjectContext:context];
//NSRelationshipDescription *dagbokRelation = [[NSRelationshipDescription alloc] init];
//NSRelationshipDescription *vallaRelation = [[NSRelationshipDescription alloc] init];
[newDagbok setValue:text forKey:#"text"];
[newDagbok setValue:header forKey:#"header"];
[newDagbok setValue:[NSNumber numberWithInt:degree] forKey:#"degree"];
[newDagbok setValue:weather forKey:#"weather"];
[newDagbok setValue:farg forKey:#"colorCode"];
NSError *error;
if(![context save:&error])
{
NSLog(#"Whoops : %#", [error localizedDescription]);
}
}
How do i add related objects from an array with fetchRequest results?
Life will be much easier if you create NSManagedObject sub classes to represent your entities rather than dealing with NSManagedObject directly. Do this by adding a name for your class in the model (the "class" property of the entity), e.g. for Valla set to VallaEntity. Then XCode can autogenerate these classes which will then have properties and methods to simplify your code, e.g.
DagbokEntity *newDagbok = [[NSManagedObject alloc] initWithEntity:entitydesc insertIntoManagedObjectContext:context];
newDagbok.text = text;
newDagbok.header = header;
newDagbok.degree = [NSNumber numberWithInt:degree];
newDagbok.weather = weather;
newDagbok.colorCode = farg;
[newDagbok addVallas:[NSSet setWithArray:arrayOfRelatedVallas]];
First question here and I've tried a bunch of stuff and can't figure it out.
Core Data with 2 entities with to-many relationship both ways
A<<---->>B
A entity has name as an attribute, and a relationship Bs
First Controller lists all A entities and i have a second controller to add A entities and I want to have it save a default B in its relationship.
In the prepare for segue I have this code:
if ([[segue identifier] isEqualToString:#"addAEntitySegue"]) {
AddAEntityViewController *addAEntityViewController = [segue destinationViewController];
addAEntityViewController.delegate = self;
addAEntityViewController.managedObjectContext = self.managedObjectContext;
NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
self.addingManagedObjectContext = addingContext;
[addingManagedObjectContext setPersistentStoreCoordinator:[[fetchedResultsController managedObjectContext] persistentStoreCoordinator]];
addAEntityViewController.A = [NSEntityDescription insertNewObjectForEntityForName:#"A" inManagedObjectContext:addingContext];
UIBarButtonItem *saveButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave
target:addAEntityViewController
action:#selector(save:)];
addAEntityViewController.navigationItem.rightBarButtonItem = saveButton;
}
In addAEntityViewController i have this to save
-(IBAction)save:(id)sender
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"B" inManagedObjectContext:self.managedObjectContext];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#",[defaults objectForKey:#"BDefault"]];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:predicate];
//Set the batch size to a suitable number
[fetchRequest setFetchBatchSize:20];
NSError *error;
self.A.name = textFieldVal;
[self.A addBObject:[[self.managedObjectContext executeFetchRequest:fetchRequest error:&error] objectAtIndex:0]];
NSLog(#"A = %#", self.A.Bs);
[self.delegate addAEntityViewController:self didFinishWithSave:YES];
}
In the addAEntityViewController everything saves correctly even the NSLog(#"A = %#", self.A.Bs); statement shows the B. But when the delegate saves in the First Controller (AEntityViewController) it only saves the A.name but not the relationship A.Bs, I can't figure out what's wrong.
Here's the delegate method:
-(void) addAEntityViewController:self didFinishWithSave:YES{
if (save) {
NSLog(#"saveworkouts");
NSError *error;
if (![addingManagedObjectContext save:&error]) {
// Update to handle the error appropriately.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1); // Fail
}
}
// release the adding managed object context
self.addingManagedObjectContext = nil;
}
Like I said it saves the A entity but not the relationship to B even though the relationship to B saved correctly in the addAEntityViewController (the second View). An NSLOg of A.Bs is null.
First I believe that this line:
addAEntityViewController = self.managedObjectContext;
should be:
addAEntityViewController.managedObjectContext = self.managedObjectContext;
but that would also be wrong.
it should be getting the addingContext you created afterwards:
addAEntityViewController.managedObjectContext = addingContext;
I'm a bit surprised that your app didn't crash, as you are mixing managed objects from 2 different contexts.