Add to arrayController, edit Core Data attribute - objective-c

***** EDIT *****
What I'm not sure of is how to access an entity from the model in the code, and how to access a specific instance of an entity in that code. That sums up the main issues I'm having.
***** END EDIT *****
I have a tableview with a button to add to it. When the button is clicked, the user is presented with an open dialog where they select a file(s). A new Object is added to the array controller. What I'm not sure how to do is to edit the core data attributes for this new object. There are two attributes, filename and pathname, and I'm not sure how to edit them. If you look at the bottom of the openPanelDidEnd:returnCode:contextInfo: function you'll see what I'm trying to accomplish.
- (IBAction)addAttachment:(id)sender
{
panel = [NSOpenPanel openPanel];
[panel beginSheetForDirectory:nil
file:nil
modalForWindow:[NSApp mainWindow]
modalDelegate:self
didEndSelector:#selector(openPanelDidEnd:
returnCode:
contextInfo:)
contextInfo:NULL];
}
- (void)openPanelDidEnd:(NSOpenPanel *)openPanel
returnCode:(int)returnCode
contextInfo:(void *)x
{
if (returnCode == NSOKButton)
{
NSArray *files = [openPanel filenames];
int i;
for (i = 0; i < [files count]; i++)
{
NSString *file = [files objectAtIndex:i];
[attachmentController add:x];
// How do I add filenames here?
// I'm assuming it involves KVC like
// [something setValue:#"file" forKey:#"filename"];
// But I don't know hot to get the something
// i.e. since I have multiple attachments,
// how do I get the one I just created
}
}
}
*********** EDIT **************
Simplified, my model has 2 entities: Attachment and Item. Item has a to-many relationship with Attachment, as each Item may have many Attachment's.
My openPanelDidEnd:returnCode:contextInfo: method now looks like this:
NSString *filename = [files objectAtIndex:i];
MySchoolPlanner_AppDelegate *myAppDelegate = [[MySchoolPlanner_AppDelegate init] alloc];
[NSEntityDescription insertNewObjectForEntityForName:#"Attachment"
inManagedObjectContext:[myAppDelegate managedObjectContext]];
[myAppDelegate release];
For some reason, the table view bound to the Attachment array controller does not add any. Also, I'm not sure how to access the attachment I just created to use KVC on it.

NSArray's add: method is something you'd hook a button up to, when you have a Core Data entity that can be created and used without any initialization. In this case just call NSEntityDescription's
+ (id)insertNewObjectForEntityForName:(NSString *)entityName inManagedObjectContext:(NSManagedObjectContext *)context
with the managed object context you're using with your array controller and the appropriate entity name to create your managed object in code. You can set properties on it directly if you've created a subclass for your entity, or just use key value coding if you haven't done that yet.

Related

How do I display my Core Data values?

I have a basic UITableView where I can add items using Core Data as well as delete if needed.
Let's say I add 5 items to the UITableView. I want to also display these five items on another view, preferably a PDF.
What's the best approach to accomplish this?
I'm attempting using NSUserDefaults as well, but the only value that is appearing is the last value that is entered.
Here's some of the main code used. Any advice is appreciated!
This is from the UIViewController where I input the text:
-(NSManagedObjectContext * )managedObjectContext
{
return [(AppDelegate *) [[UIApplication sharedApplication] delegate] managedObjectContext];
}
-(void)saveButtonTapped:(id)sender
{
[self.managedObjectContext save:nil];
if (_majorTextField.text == nil)
{
_majorString = #"";
}
else
{
_majorString = [[NSString alloc] initWithFormat:#"%#", _majorTextField.text];
self.task.title = self.majorTextField.text;
NSUserDefaults * majorDefault = [NSUserDefaults standardUserDefaults];
[majorDefault setObject:_majorString forKey:#"major"];
}
[self.navigationController popViewControllerAnimated:YES];
}
Here is where I am adding the text on my PDF:
+(void)createPDF:(NSString*)filePath
{
// Create the PDF context using the default page size of 612 x 792.
UIGraphicsBeginPDFContextToFile(filePath, CGRectZero, nil);
// Mark the beginning of a new page.
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, 612, 792), nil);
NSUserDefaults * majorDefault = [NSUserDefaults standardUserDefaults];
NSString * majorString = [majorDefault stringForKey:#"major"];
[PDFRenderer drawText:majorString inFrame:CGRectMake(35, 190, 300, 50) fontName:#"TimesNewRomanPSMT" fontSize:14];
UIGraphicsEndPDFContext();
}
You are saving your NSManagedObjectContext before you make changes to the represented object in your view controller. In saveButtonTapped: you save the context but only later set self.task.title ... Perhaps I'm missing something; but I think you want save the context after changing self.task.title.
In the other views that need to access the managed objects in question, you need to fetch them by constructing an NSFetchRequest and executing that request against an NSManagedObjectContext. I can't give any substantial example without knowing more about your model; but that's the basic idea.
Depending on your needs, Core Data may be ideal or it may be overkill. There's a lot to be gained by using Core Data for your object graph persistence technology - but there's a lot of subtlety. As Apple puts it. "Core Data is not an entry level technology." (Apple, "Getting Started with Core Data")
We're probably all guilty of this, but you should pass an error object in [self.managedObjectContext save:nil]; and handle the return value, thusly:
NSError *saveError = nil;
if( ![[self managedObjectContext] save:&saveError] ) {
// do something with saveError
}
EDIT:
Core Data is fine for what you describe in your comment. It's just a matter of understanding the underlying principles of persistent stores, managed object contexts, etc. What you do get with Core Data are a set of conveniences for displaying data in table views, i.e. NSFetchedResultsController.

Fetching a one-to-many core data relationship returns correct objects the first time but empty set all other times

I have an object, Workout, that has a one-to-many relationship with an object, Exercise.
Diagram of models: http://i.imgur.com/q1Mfq.png
When I create a Workout object, I add three Exercise objects to it by looping over
[self addExercisesObject:exercise]
and then save my managed object context. Then, from my controller for displaying a workout, I can successfully fetch the workout and its exercises (with a fetch request), as shown by the output in my debugger:
Printing description of self->_savedWorkout:
<Workout: 0x6c5a990> (entity: Workout; id: 0x6e46e00 <x-coredata://EA417EAA-101A-4F04-8276-3C4A6CDF094D/Workout/p1> ; data: {
bodyweight = nil;
date = "2012-05-09 16:59:43 +0000";
exercises = (
"0x6e3c870 <x-coredata://EA417EAA-101A-4F04-8276-3C4A6CDF094D/Exercise/p3>",
"0x6e3eaf0 <x-coredata://EA417EAA-101A-4F04-8276-3C4A6CDF094D/Exercise/p2>",
"0x6e36820 <x-coredata://EA417EAA-101A-4F04-8276-3C4A6CDF094D/Exercise/p1>"
);
isCompleted = 0;
workoutId = 1;
workoutPlan = "0x6e6c980 <x-coredata://EA417EAA-101A-4F04-8276-3C4A6CDF094D/WorkoutPlan/p1>";
})
So far so good. However, if I close my app in my simulator and start it up again and perform the same fetch request in same view, the workout looks like this:
Printing description of self->_savedWorkout:
<Workout: 0x6ea8ff0> (entity: Workout; id: 0x6e8f9e0 <x-coredata://EA417EAA-101A-4F04-8276-3C4A6CDF094D/Workout/p1> ; data: {
bodyweight = nil;
date = "2012-05-09 16:59:43 +0000";
exercises = (
);
isCompleted = 0;
workoutId = 1;
workoutPlan = "0x6c8a130 <x-coredata://EA417EAA-101A-4F04-8276-3C4A6CDF094D/WorkoutPlan/p1>";
})
It appears that it fetches the same workout object, but now exercises is an empty set. Actually, exercises first looks like this after the fetch request:
exercises = "<relationship fault: 0x8a93100 'exercises'>";
but once I do:
for (Exercise *exercise in self.savedWorkout.exercises)
self.savedWorkout.exercises resolves to an empty set. I do not edit the workout in anyway in any part of my app.
My fetch request is made by this method in my Workout class:
- (Workout *)getLatestWorkout
{
self.model = [[self.managedObjectContext persistentStoreCoordinator] managedObjectModel];
NSFetchRequest *fetchRequest = [self.model fetchRequestTemplateForName:#"getLatestWorkout"];
NSError *error = nil;
NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if ([results count] == 1) {
return [results objectAtIndex:0];
}
return nil;
}
I made the fetch request template with Xcode's GUI tool. It fetches all Workout objects where isCompleted == 0. You can see that it fetches the same object each time because the workout's x-coredata path is the same in both debugger outputs.
Update: I checked my SQLite database. There is one workout in the workout table and three exercises in the exercises table.
Any ideas what's going on?
EDIT: Code that creates objects posted below
- (void)storeUserSettings
{
// get the file path if it exists
NSString *path = [[NSBundle mainBundle] pathForResource:#"userSettings" ofType:#"plist"];
// create it if it doesn't
if (path == nil) {
path = [NSString stringWithFormat:#"%#%#",
[[NSBundle mainBundle] bundlePath], #"/userSettings.plist"];
}
// and write the new settings to file
[self.userSettings writeToFile:path atomically:YES];
// load managed object context
[self loadMOC];
WorkoutPlan *currentPlan = [[WorkoutPlan alloc] getActiveWorkoutPlan];
[currentPlan setManagedObjectContext:self.managedObjectContext];
// if user has no plan or is changing plans, create new plan and first workout
if (currentPlan == nil ||
([self.userSettings valueForKey:#"plan"] != currentPlan.planId)) {
// create a workoutPlan object
WorkoutPlan *workoutPlan = [[WorkoutPlan alloc] initWithEntity:
[NSEntityDescription entityForName:#"WorkoutPlan"
inManagedObjectContext:self.managedObjectContext]
insertIntoManagedObjectContext:self.managedObjectContext];
// set attributes to values from userSettings and save object
[workoutPlan createWorkoutPlanWithId:[self.userSettings valueForKey:#"plan"]
schedule:[self.userSettings valueForKey:#"schedule"]
dateStarted:[self.userSettings valueForKey:#"nextDate"]];
}
// if user is just changing schedule, update schedule of current plan
else if (![currentPlan.schedule isEqualToString:[self.userSettings valueForKey:#"schedule"]]) {
[currentPlan setSchedule:[self.userSettings valueForKey:#"schedule"]];
[currentPlan saveMOC];
}
}
- (void)loadMOC
{
AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
self.managedObjectContext = delegate.managedObjectContext;
self.model = [[self.managedObjectContext persistentStoreCoordinator] managedObjectModel];
}
- (void)createWorkoutPlanWithId:(NSNumber *)planId schedule:(NSString *)schedule
dateStarted:(NSDate *)dateStarted
{
[self deactivateCurrentPlan];
// set workout plan attributes
[self setPlanId:planId];
[self setIsActive:[NSNumber numberWithBool:YES]];
[self setSchedule:schedule];
[self setDateStarted:dateStarted];
// create first workout and add to workout plan
Workout *firstWorkout = [NSEntityDescription
insertNewObjectForEntityForName:#"Workout"
inManagedObjectContext:self.managedObjectContext];
[firstWorkout setManagedObjectContext:self.managedObjectContext];
[firstWorkout createFirstWorkoutForPlan:self onDate:dateStarted];
[self addWorkoutsObject:firstWorkout];
[self saveMOC];
}
- (void)createFirstWorkoutForPlan:(WorkoutPlan *)plan onDate:(NSDate *)startDate
{
// set workout attributes
[self setDate:startDate];
[self setIsCompleted:[NSNumber numberWithBool:NO]];
[self setWorkoutId:[NSNumber numberWithInt:1]];
NSArray *exerciseList = [self getExercisesForWorkout:self inPlan:plan];
// iterate over exercises in spec and create them
for (NSDictionary *exerciseSpec in exerciseList)
{
// create a exercise MO
Exercise *exercise = [NSEntityDescription
insertNewObjectForEntityForName:#"Exercise"
inManagedObjectContext:[plan managedObjectContext]];
[exercise setManagedObjectContext:[plan managedObjectContext]];
[exercise createExerciseForWorkout:self withSpec:exerciseSpec];
// add exercise to workout object
[self addExercisesObject:exercise];
}
}
- (void)createExerciseForWorkout:(Workout *)workout withSpec:exerciseSpec
{
// set exercise attributes
self.exerciseId = [exerciseSpec valueForKey:#"id"];
self.isPersonalRecord = [NSNumber numberWithBool:NO];
NSArray *sets = [exerciseSpec valueForKey:#"sets"];
int i = 1;
for (NSNumber *setReps in sets)
{
// create a set MO
Set *set = [NSEntityDescription
insertNewObjectForEntityForName:#"Set"
inManagedObjectContext:[workout managedObjectContext]];
[set setManagedObjectContext:[workout managedObjectContext]];
// set set attributes
set.order = [NSNumber numberWithInt:i];
set.repetitions = setReps;
set.weight = [exerciseSpec valueForKey:#"default_weight"];
// add set to exercise object
[self addSetsObject:set];
i++;
}
}
I had a similar problem. The parent-child relationship worked when the app was running but after re-start only the latest child record was retrieved.
I was adding the children like this:
create the child record
set the child's parent attribute, set the child's other
attributes
add the child to the parent using the parent's add method
I found that it was fixed if I did it like this:
create the child record
add the child to the parent using the parent's add method
set the child's parent attribute, set the child's other
attributes
Core Data is complex. There could be dozens of things to check, any one thing which could be causing issues.
How many MOCs are you using? How are you saving? Many more questions...
I would suggest turning on the SQL debugging flag (-com.apple.CoreData.SQLDebug 1) in the EditScheme for arguments when starting the application.
Run your code, and see what is actually going on.
Relationships resolve to a fault when fetched, unless you override it in the fetch request.
If you are using more than one MOC in a parent/child relationship, the save from the child to the parent just puts data into the parent, it does not really save it. If using UIManagedDocument, it's a whole different set of issues...
I hope this does not sound harsh. Be prepared to provide a whole lot of information for a Core Data question, other than "this is not saving and here is some debugging output."
Basically, how CoreData works depends on how the stack is created, whether using UIManagedDocument or not, multiple threads, how creating objects, how saving them, options on fetch requests, and a whole lot more things.
It's actually not that complex, but there are lots of customizations and special cases depending on how it is used.
EDIT
Post the code that creates the objects/relationships.
Also, try the fetch with a manual fetch request instead of the template. When you look at the data in the database, do you see the foreign keys for the relationships set appropriately?
Run it all again with debugging enabled to see exactly what the SQL is doing. That is more valuable that your own debugging output.
I'm having this exact same problem but my model is pretty complex. My app creates the entities and relationships on startup if they don't already exist. If they are created and I don't exit the app, I'm able to fetch an entity with a to-many relationship and see the correct count of related objects. If I exit my app and restart it (it now knows it doesn't have to create a default set of data) then the relationships are returning a null set. I can't figure it out.
EDIT: I figured out that my problem relates to an Ordered set relation. I had to use a Category to create a work around (found on stack overflow) to insert new entries into an ordered set. So I'm guessing that has something to do with it.

writing data from two JSON files into core data model with relation

in my application which contains a list of users with an field relating to offices i load two JSON files from a remote server. one file containing users, one file containing the offices.
my core data model contains of two entities: User and Office. they relate to each other. in user there´s a relation named office. so far so good.
but now i have to fill the fields in the entity User what works great. the list is already there. fine! but when filling the entity User with data from JSON i have to grab the appropriate managedObject from the Office entity to pass it to the User item in the User entity.
i´ve defined the office property already in the User class
#property (nonatomic, retain) NSManagedObject *office;
but what makes me headache is i have only one managedObjectContext which i´ve defined in the appDelegate. i pass the managedObjectContext to the ListViewController. see bellow:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSManagedObjectContext *context = [self managedObjectContext];
if (!context) {
// Handle the error.
}
// Pass the managed object context to the view controller.
listViewController.managedObjectContextUser = context;
// Override point for customization after application launch.
// Add the tab bar controller's current view as a subview of the window
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque animated:NO];
return YES;
}
but if i try to access a second managedObject for Office i´ve previously declared in the header it throws an exception:
- (void)updateUsers
{
NSString *users = [[NSString alloc] initWithContentsOfURL:[NSURL URLWithString:kUsersFilePath]];
if ([users length] == 0)
{
NSLog(#"usersList is == 0");
[users release];
return;
}
SBJsonParser *parser = [[SBJsonParser alloc] init];
usersObject = [[parser objectWithString:users error:nil] copy];
usersList = [usersObject objectForKey:kUsersDataName];
[parser release];
User *user = (User *)[NSEntityDescription entityForName:#"User" inManagedObjectContext:managedObjectContextUser];
NSError *error = nil;
Office *office = (Office *)[NSEntityDescription entityForName:#"Office" inManagedObjectContext:managedObjectContextOffice];
NSLog(#"managedObjectContextOffice: %#", office);
my question is do i have to create a second managedObjectContext in my appDelegate. one for User and one for Office?
Or is there a way how i can handle fetching objects from two different entities with only one managedObjectContext in the ListViewController?
Of course, the managedObjectContext refers to the whole data model, so you can do everything with your entities with that context.
After reading in a new User or Office object, try to actually create a new object by inserting it into the managedObjectContext:
User *user = [NSEntityDescription
insertNewObjectForEntityForName:#"User"
inManagedObjectContext:self.managedObjectContext];
Use the automatically generated methods in your class to attach office objects to users and vice versa.

Bindings with NSManagedObject from child context only working for NEW objects

Background:
In my app, I'm specifically targeting Mac OS X Lion. This issue involves Core Data, an NSPopover and a child NSManagedObjectContext (created by using the new parentContext property of NSManagedObjectContext).
I have a table of NSManagedObjects of class "Location". There's an Add button that calls addLocation: and if a table row is double-clicked, I call tableViewDoubleClick:.
For either case, what I do is create a new NSManagedObjectContext and set its parent context to that of the document's context. I then either create a new Location in that context or fetch the Location to be edited from the temporary context. I set the popover's representedObject property to the location in question. If I cancel the popover, nothing is saved. If the user clicks a Save button in the popover, I just call save: on the temporary context and the changes get pushed to the main context.
addLocation:
- (IBAction)addLocation:(id)sender
{
LocationEditViewController *popupController = [[[LocationEditViewController alloc] init] autorelease];
popupController.title = #"Add New Location";
NSManagedObjectContext *tempContext = [[[NSManagedObjectContext alloc] init] autorelease];
tempContext.parentContext = self.document.managedObjectContext;
Location *tempLocation = [NSEntityDescription insertNewObjectForEntityForName:#"Location" inManagedObjectContext:tempContext];
popupController.representedObject = tempLocation;
popupController.managedObjectContext = tempContext;
[popupController.popover showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMaxYEdge];
}
tableViewDoubleClick:
- (void)tableViewDoubleClick:(id)sender
{
NSInteger selectedRow = [self.table selectedRow];
if (selectedRow != -1)
{
NSRect rectOfSelectedRow = [self.table rectOfRow:selectedRow];
LocationEditViewController *popupController = [[[LocationEditViewController alloc] init] autorelease];
popupController.title = #"Edit Location";
Location *locationToEdit = [self.locationController.selectedObjects objectAtIndex:0];
NSManagedObjectContext *tempContext = [[[NSManagedObjectContext alloc] init] autorelease];
tempContext.parentContext = self.document.managedObjectContext;
Location *tempLocation = (Location *)[tempContext fetchObjectEqualTo:locationToEdit]; // Custom fetch helper method
popupController.managedObjectContext = tempContext;
popupController.representedObject = tempLocation;
[popupController.popover showRelativeToRect:rectOfSelectedRow ofView:sender preferredEdge:NSMaxXEdge];
}
}
Here's the problem that I'd like an explanation for:
The text fields in the popover are connected to the popover's representedObject via bindings in the nib. These work perfectly with a new object (addLocation:).
If the Location is an existing object (tableViewDoubleClick:), the bindings work well enough to pre-populate the fields with the Location's properties. However, changing the text in the fields does not alter the Location's properties at all. When the Save button in the popup is clicked, I tried logging the Location's properties before saving the temporary context. If it's an existing object, whatever I type into the fields isn't being reflected in the Location's properties - as if the bindings are only communicating one-way.
My workaround: I found that if I skip the bindings and just manually set the Location's properties to the values in the text fields before the save, that the changes do take effect.
- (IBAction)popoverSave:(id)sender
{
// These two methods always work. But if I remove these and use bindings instead, it only works for NEW Locations.
[(Location *)self.representedObject setLabel:self.labelField.stringValue];
[(Location *)self.representedObject setLocation:self.locationField.stringValue];
NSLog(#"representedObject = %#", self.representedObject);
NSError *error = nil;
[self.managedObjectContext save:&error];
[self.popover close];
}
I'd really like to know why this is the case, just in case I'm actually doing something wrong.
Thanks!
I think it's likely that it is the cast in these lines:
[(Location *)self.representedObject setLabel:self.labelField.stringValue];
[(Location *)self.representedObject setLocation:self.locationField.stringValue];
… that makes them work. If so, then you probably have a NSObject or NSManagedObject set somewhere in the bindings as the class instead of the Location class. When the binding sends a Location class specific message e.g. set an attribute with a specific name, to the generic class, the generic class silently ignores the message.
BTW, I would caution against using multiple context instead of using the undo API. I see a lot of people get in trouble that way. It's easier to roll back a single context than it is to manage multiple context.

Adding a new record programmatically to a Cocoa Core Data Entity

i'm making a simple document-based application in Cocoa. Each document of this app should basically manage an array of Dates and Notes, so each record is a date and a note (textview). Also each document is protected by password.
To do that i created a Core Data entity called HistoryElement (that contains a date and a notes attribute), i also created a Settings entity that should have only a record which contains the password to open the file (i didn't found a better method, there is one ? The password is tied to each file, so i can't use preferences because it's not a global application password).
I have a preference tab which contain a Password textfield that binds to the password attribute of the Settings entity.
Ok...the problem is now this: when i create a new document there are no records on the Settings entity, so i wish to programmatically add one, so the user can put (if it want to protect it's file) the password in the password text field.
Instead, if i'm opening an existing file it should find that a record for Settings entity has been already add and it shouldn't create it again, instead the password text field should use this one.
I tried many ways, but i'm unable to do that. I tried for example this:
if([[settingsArrayController arrangedObjects] count] == 0) {`
NSLog(#"Init settings");`
[settingsArrayController add:self];`
}
It seems that it adds a new record when i create a new document, but if i put a password in the password text field and then save the document, when i open the document again the [[settingsArrayController arrangedObjects] count] returns 0 and it creates a new record again...
How can i do that ? There is a better/simple/elegant way to protect a document with a password ?
You need to add the code to NSPersistentDocument after the managedObjectContext has been initialized and the data has been loaded. It's hard to say what's wrong with the sample code you posted without knowing where you put it.
One easy place you could put it is in the windowControllerDidLoadNib. For example,
- (void)windowControllerDidLoadNib:(NSWindowController *)windowController
{
[super windowControllerDidLoadNib:windowController];
// user interface preparation code
NSManagedObjectContext *moc = [self managedObjectContext];
NSSet *settings = [moc fetchObjectsForEntityName:#"Settings"
withPredicate:nil];
if ([settings count] == 0)
{
NSManagedObject *obj = [NSEntityDescription insertNewObjectForEntityForName:#"Settings"
inManagedObjectContext:moc];
[obj setValue:#"myPass" forKey:#"password"];
} else {
// password record already exists, do something else.
}
}
Note that I am using a category on NSManagedObjectContext that does all the boiler plate query stuff:
// Convenience method to fetch the array of objects for a given Entity
// name in the context, optionally limiting by a predicate or by a predicate
// made from a format NSString and variable arguments.
//
- (NSSet *)fetchObjectsForEntityName:(NSString *)newEntityName
withPredicate:(id)stringOrPredicate, ...
{
NSEntityDescription *entity = [NSEntityDescription
entityForName:newEntityName inManagedObjectContext:self];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entity];
if (stringOrPredicate)
{
NSPredicate *predicate;
if ([stringOrPredicate isKindOfClass:[NSString class]])
{
va_list variadicArguments;
va_start(variadicArguments, stringOrPredicate);
predicate = [NSPredicate predicateWithFormat:stringOrPredicate
arguments:variadicArguments];
va_end(variadicArguments);
}
else
{
NSAssert2([stringOrPredicate isKindOfClass:[NSPredicate class]],
#"Second parameter passed to %s is of unexpected class %#",
sel_getName(_cmd), [stringOrPredicate className]);
predicate = (NSPredicate *)stringOrPredicate;
}
[request setPredicate:predicate];
}
NSError *error = nil;
NSArray *results = [self executeFetchRequest:request error:&error];
if (error != nil)
{
[NSException raise:NSGenericException format:#"%#",[error description]];
}
return [NSSet setWithArray:results];
}
And that should be all there is to it.
I have created a quick sample project that illustrates what you need to do at: http://dl.dropbox.com/u/21359504/coredata-example.zip