Core Data unique attributes - objective-c

Is it possible to make a Core Data attribute unique, i.e. no two MyEntity objects can have the same myAttribute?
I know how to enforce this programatically, but I'm hoping there's a way to do it using the graphical Data Model editor in xcode.
I'm using the iPhone 3.1.2 SDK.

Every time i create on object I perform a class method that makes a new Entity only when another one does not exist.
+ (TZUser *)userWithUniqueUserId:(NSString *)uniqueUserId inManagedObjectContext:(NSManagedObjectContext *)context
{
TZUser *user = nil;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:#"TZUser" inManagedObjectContext:context];
request.predicate = [NSPredicate predicateWithFormat:#"objectId = %#", uniqueUserId];
NSError *executeFetchError = nil;
user = [[context executeFetchRequest:request error:&executeFetchError] lastObject];
if (executeFetchError) {
NSLog(#"[%#, %#] error looking up user with id: %i with error: %#", NSStringFromClass([self class]), NSStringFromSelector(_cmd), [uniqueUserId intValue], [executeFetchError localizedDescription]);
} else if (!user) {
user = [NSEntityDescription insertNewObjectForEntityForName:#"TZUser"
inManagedObjectContext:context];
}
return user;
}

From IOS 9 there is a new way to handle unique constraints.
You define the unique attributes in the data model.
You need to set a managed context merge policy "Merge policy singleton objects that define standard ways to handle conflicts during a save operation" NSErrorMergePolicy is the default,This policy causes a save to fail if there are any merge conflicts.
- (NSManagedObjectContext *)managedObjectContext {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (!coordinator) {
return nil;
}
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
[_managedObjectContext setMergePolicy:NSOverwriteMergePolicy];
return _managedObjectContext;
}
The various option are discussed at Apple Ducumentation Merge Policy
It is answered nicely here
Zachary Orr's Answer
and he has kindly also created a blogpost and sample code.
Sample Code
Blog Post
The most challenging part is to get the data Model attributes editable.The Secret is to left click and then right click, after you have clicked the + sign to add a constraint.

I've decided to use the validate<key>:error: method to check if there is already a Managed Object with the specific value of <key>. An error is raised if this is the case.
For example:
- (BOOL)validateMyAttribute:(id *)value error:(NSError **)error {
// Return NO if there is already an object with a myAtribute of value
}
Thanks to Martin Cote for his input.

You could override the setMyAttribute method (using categories) and ensure uniqueness right there, although this may be expensive:
- (void)setMyAttribute:(id)value
{
NSArray *objects = [self fetchObjectsWithMyValueEqualTo:value];
if( [objects count] > 0 ) // ... throw some exception
[self setValue:value forKey:#"myAttribute"];
}
If you want to make sure that every MyEntity instance has a distinct myAttribute value, you can use the objectID of the NSManagedObject objects for that matter.

I really liked #DoozMen approach!!
I think it's the easiest way to do what i needed to do.
This is the way i fitted it into my project:
The following code cycles while drawing a quite long tableView, saving to DB an object for each table row, and setting various object attributes for each one, like UISwitch states and other things: if the object for the row with a certain tag is not present inside the DB, it creates it.
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:#"Obiettivo" inManagedObjectContext:self.managedObjectContext];
request.predicate = [NSPredicate predicateWithFormat:#"obiettivoID = %d", obTag];
NSError *executeFetchError = nil;
results = [[self.managedObjectContext executeFetchRequest:request error:&executeFetchError] lastObject];
if (executeFetchError) {
NSLog(#"[%#, %#] error looking up for tag: %i with error: %#", NSStringFromClass([self class]), NSStringFromSelector(_cmd), obTag, [executeFetchError localizedDescription]);
} else if (!results) {
if (obbCD == nil) {
NSEntityDescription *ent = [NSEntityDescription entityForName:#"Obiettivo" inManagedObjectContext:self.managedObjectContext];
obbCD = [[Obiettivo alloc] initWithEntity:ent insertIntoManagedObjectContext:self.managedObjectContext];
}
//set the property that has to be unique..
obbCD.obiettivoID = [NSNumber numberWithUnsignedInt:obTag];
[self.managedObjectContext insertObject:obbCD];
NSError *saveError = nil;
[self.managedObjectContext save:&saveError];
NSLog(#"added with ID: %#", obbCD.obiettivoID);
obbCD = nil;
}
results = nil;

Take a look at the Apple documentation for inter-property validation. It describes how you can validate a particular insert or update operation while being able to consult the entire database.

You just have to check for an existing one :/
I just see nothing that core data really offers that helps with this. The constraints feature, as well as being broken, doesn't really do the job. In all real-world circumstances you simply need to, of course, check if one is there already and if so use that one (say, as the relation field of another item, of course). I just can't see any other approach.
To save anyone typing...
// you've download 100 new guys from the endpoint, and unwrapped the json
for guy in guys {
// guy.id uniquely identifies
let g = guy.id
let r = NSFetchRequest<NSFetchRequestResult>(entityName: "CD_Guy")
r.predicate = NSPredicate(format: "id == %d", g)
var found: [CD_Guy] = []
do {
let f = try core.container.viewContext.fetch(r) as! [CD_Guy]
if f.count > 0 { continue } // that's it. it exists already
}
catch {
print("basic db error. example, you had = instead of == in the pred above")
continue
}
CD_Guy.make(from: guy) // just populate the CD_Guy
save here: core.saveContext()
}
or save here: core.saveContext()
core is just your singleton, whatever holding your context and other stuff.
Note that in the example you can saveContext either each time there's a new one added, or, all at once afterwards.
(I find tables/collections draw so fast, in conjunction with CD, it's really irrelevant.)
(Don't forget about .privateQueueConcurrencyType )
Do note that this example DOES NOT show that you, basically, create the entity and write on another context, and you must use .privateQueueConcurrencyType You can't use the same context as your tables/collections .. the .viewContext .
let pmoc = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
pmoc.parent = core.container.viewContext
do { try pmoc.save() } catch { fatalError("doh \(error)")}

Related

Objective C - Firebase - How to add completion handler to FDataSnapshot

I'm experimenting with Firebase's FDataSnapshot to pull in data and I would like it to write its data to my core data using MagicalRecord.
According to Firebases "best practice" blog I need to keep a reference to the "handle" so it can be cleaned up later on. Further, they mention to put the FDSnapshot code in viewWillAppear.
I am wanting a callback so that when its finished doing its thing to update core data.
But I'm really note sure how to do that; its doing two things and giving a return at the same time.
// In viewWillAppear:
__block NSManagedObjectContext *context = [NSManagedObjectContext MR_context];
self.handle = [self.ref observeEventType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {
if (snapshot.value == [NSNull null])
{
NSLog(#"Cannot find any data");
}
else
{
NSArray *snapshotArray = [snapshot value];
// cleanup to prevent duplicates
[FCFighter MR_truncateAllInContext:context];
for (NSDictionary *dict in snapshotArray)
{
FCFighter *fighter = [FCFighter insertInManagedObjectContext:context];
fighter.name = dict[#"name"];
[context MR_saveToPersistentStoreWithCompletion:^(BOOL contextDidSave, NSError *error){
if (error)
{
NSLog(#"Error - %#", error.localizedDescription);
}
}];
}
}
}];
NSFetchRequest *fr = [[NSFetchRequest alloc] initWithEntityName:[FCFighter entityName]];
fr.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES]];
self.fighterList = (NSArray *) [context executeFetchRequest:fr error:nil];
[self.tableView reloadData];
In the above code, the core data reading does not wait for the firebase to complete.
Thus, my query -- how would I best combine a completion handler so that when it is complete to update core data, and reload the tableview.
Many thanks
This is a common issue when working with Asynchronous data.
The bottom line is that all processing of data returned from an async call (in this case, the snapshot) needs to be done inside the block.
Anything done outside the block may happen before the data is returned.
So some sudo code
observeEvent withBlock { snapshot
//it is here where snapshot is valid. Process it.
NSLog(#"%#", snapshot.value)
}
Oh, and a side note. You really only need to track the handle reference when you are going to do something else with it later. Other than that, you can ignore the handles.
So this is perfectly valid:
[self.ref observeEventType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {
//load your array of tableView data from snapshot
// and/or store it in CoreData
//reload your tableview
}

Fixing delay in Core Data Storage

So I am building in a hide function into my application. In my settings menu I have a UISwitch that should allow the user to hide themselves. I have created the UISwitch's IBAction like so:
-(IBAction)hideUserToggle:(id)sender {
AppDelegate *newAppDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [newAppDelegate managedObjectContext];
NSManagedObject *newOwner;
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:#"LoggedInUser" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
NSManagedObject *matches = nil;
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
newOwner = [NSEntityDescription insertNewObjectForEntityForName:#"LoggedInUser" inManagedObjectContext:context];
if (_hideUser.on) {
if ([objects count] == 0) {
NSLog(#"%#",[error localizedDescription]);
} else {
matches = objects[0];
[newOwner setValue:#"userHidden" forKeyPath:#"isHidden"];
NSLog(#"%#",[matches valueForKeyPath:#"isHidden"]);
}
} else {
if([objects count] == 0) {
NSLog(#"%#",[error localizedDescription]);
} else {
matches = objects[0];
[newOwner setValue:#"userNotHidden" forKeyPath:#"isHidden"];
NSLog(#"%#",[matches valueForKeyPath:#"isHidden"]);
}
}
}
This should set the value of the Core Data String that I use to determine whether a person is hidden or not, which I use later in my code as a conditional for loading data. However when I test this feature it doesn't seem to update the persistent data store (Core Data) when the user has flipped the switch. I have looked around everywhere and I found a reference to there being a delay in updating Core Data here -> Why does IOS delay when saving core data via a UIManagedDocument, however it doesn't seem to provide the answer to my problem.
I want to be able flip the switch and save that value so that when the user swipes over to another view controller it is immediately aware that the user has gone into "hiding" or offline so it does not show certain information.
A NSManagedObjectContext is a scratchpad. Changes you make within the context exist only within the context unless or until you save them to the context's parent (either the persistent store itself or another context).
You're not saving them. I'd assume you're therefore not seeing the change elsewhere because you're using different contexts. Meanwhile the change eventually migrates because somebody else happens to save.
See -save: for details on saving.
(aside: the key-value coding [newOwner setValue:#"userHidden" forKeyPath:#"isHidden"]-style mechanism is both uglier and less efficient than using an editor-generated managed object subclass; hopefully it's just there while you're debugging?)

Why is Core Data losing one of my values?

Inside my user object I have the following code to generate a new 'session' or continue the existing session if one exists.
Strangely it will keep other properties but just loses the 'user' property... user is in a one to many relationship with session, 1 user can have many sessions. (or will do, for the following test I am simply checking for any previous session and using it if it exists)
-(void)setupSessionStuff
{
// Create new Core Data request
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Session" inManagedObjectContext:[self managedObjectContext]];
[request setEntity:entity];
// Create Sort Descriptors for request
NSSortDescriptor *startTimeSort = [[NSSortDescriptor alloc] initWithKey:#"startTime" ascending:NO selector:nil];
[request setSortDescriptors:[NSArray arrayWithObjects:startTimeSort, nil]];
[startTimeSort release];
[request setFetchLimit:1]; // Only get the most recent session
// Execute request
NSError *error = nil;
NSArray *results = [[self managedObjectContext] executeFetchRequest:request error:&error];
if (results == nil) {
// Something went horribly wrong...
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1);
}
[request release];
Session *theSession = nil;
if ([results count] == 1) {
NSLog(#"existing session");
// Use existing Session
theSession = [results objectAtIndex:0];
NSLog(#"session.user: %#", [theSession valueForKey:#"user"]); // this is always null!
} else {
NSLog(#"new session");
// Create new Sesson
theSession = (Session *)[NSEntityDescription insertNewObjectForEntityForName:#"Session" inManagedObjectContext:[self managedObjectContext]];
// Add the Session to the User
NSLog(#"before: session.user: %#", theSession.user); // null
theSession.user = self;
NSLog(#"after: session.user: %#", theSession.user); // looks good
}
...
NSLog(#"before.save: session.user: %#", theSession.user); // good
// Save everything
error = nil;
if (![[self managedObjectContext] save:&error]) {
// Something went horribly wrong...
NSLog(#"Unresolved error: %#, %#, %#", error, [error userInfo],[error localizedDescription]);
exit(-1);
}
NSLog(#"after.save: session.user: %#", theSession.user); // still there..
}
Additionally I have opened up the Core Data sqlite file and examined with SQLite Manager. It looks like the relationship has been correctly saved, as I can see the userID stored in the session table.
-
Just added this at the start of my method as another test.
NSSet *set = self.session;
for(Session *sess in set) {
NSLog(#"startTime %#", sess.startTime);
NSLog(#"user %#", sess.user);
}
Strangely enough the user is set in this case!? So set here then not set a few lines later when I do the fetch request... ?
-
In response to feedback below
Have added this code after assigning session.user = self and both return the expected output. So it does look like the problem is with the subsequent fetch.
NSLog(#"self.session: %#", self.session);
NSLog(#"self.session: %#", [self valueForKey:#"session"]);
Also I agree that accessing my session's through self.session will let me work around my issue, but it doesn't solve what is going on here.
In other places I surely won't be able to walk from one entity to the other so need to confidence the fetch is going to pull everything in correctly.
Firstly, I would check that the relationship is set from the other side by logging self.session. If that shows as null then you have no reciprocal relationship set in the model.
I think that your fetch is poorly constructed. You are relying on the sort descriptor to provide the last used session but you only have a fetch limit of 1. You seem to think that the fetch will find all existing Session objects, sort them and then return the first one. However, sorts execute last so the fetch will find a single session object (because of the fetch limit) and will then apply the sort to that single object. This makes it likely that you will be dealing with a more or less random Session object.
You probably don't need a fetch at all because you are only interested in the Session objects in a relationship with the User object which is self. If you already have the object in one side of a relationship, you don't need to fetch, you just need to walk the relationship. All you really need to do is:
if ([self.session count]==0){
//...create new session and set relationship
}else{
//... find latest session
}
I think your problem with this particular chunk of code is in the reporting. When you get a return value, you use the self.user notation but where you get a null return you use valueForKey:.
While in theory both return the same value, they don't have to because they don't use the same mechanism to return the value. The self-dot notation calls an accessor method while valueForKey: may or may not depending on the specifics of a class' implementation. I would test if the self.session returns a value where valueForKey: does not.
Well I found the problem and solved my issue...
After examining the memory address of my session entity I noticing that it was changing between runs. Investigating further I discovered that where I had been testing some code earlier in another class, creating a new session entity, but not saving it, well, it was being saved after all - when I issued the save in my code above!

Core Data Saving and Loading to Multiple Entities

Core Data Noob here.
I have a project, it saves data to a single entity no problemo. However, because the entity has way too many properties (over 100) it gets a warning that I need to normalize it. OK, so i create a second entity to store more data with To-One relationships both ways.
Problem is that when i try to save data, data saves and reloads to the first entity, but will not save or reload from the second. I must be missing something simple.
Here is some code:
//ViewDidLoad
- (void)viewDidLoad
{
if (managedObjectContext == nil) {
managedObjectContext = [(CoreDataStuffAppDelegate *) [[UIApplication sharedApplication] delegate] managedObjectContext];
NSLog(#"After managedObjectContext: %#", managedObjectContext);
}
// [self addRecord];
[super viewDidLoad];
if ([self fetchData]) {
NSLog(#"after self fetchData patientArray count is %i", [parentArray count]);
if ([parentArray count] == 1) {
Parent *parentInfo = (Parent *)[parentArray objectAtIndex:0];
parentItem1.text = parentInfo.Mother;
NSLog(#"fetching on load %i", [parentArray count]);
//Try 1: just going after the relationship route (FAIL: cuz data wont store. stays null)
// childItem1.text = parentInfo.ParentToChild.Kid;
// Try 2: going the route of directly talking to the second entity
childItem1.text = child.Kid;
}
}
// Save Record
- (void)saveRecord{
if (managedObjectContext == nil) {
NSLog(#"there is no context, arrg");
}
NSLog(#"array count is %i", [parentArray count]);
if ([parentArray count] == 1) {
NSManagedObjectContext *context = managedObjectContext;//[parent managedObjectContext];
NSLog(#"context 1 is: %#", context);
Parent *parentInfo = (Parent *)[parentArray objectAtIndex:0];
parentInfo.Mother = parentItem1.text;
NSLog(#"data says: %#", parentInfo.Mother);
NSLog(#"text syas: %#", parentItem1.text);
// Try 1, save it through the child relationship thing. (failed)
// parentInfo.ParentToChild.Kid = childItem1.text;
// NSLog(#"childSave says: D: %# T: %#", parentInfo.ParentToChild.Kid , childItem1.text);
// Try 2. from Resipeas app
if (!child) {
self.child = [NSEntityDescription insertNewObjectForEntityForName:#"Child" inManagedObjectContext:context];
[parent addChildObject:child];
NSLog(#"I hit the child");
}
child.Kid = childItem1.text;
NSLog(#"1: childSave says: D: %# T: %#", parentInfo.ParentToChild.Kid , childItem1.text);
NSLog(#"2: childSave says: D: %# T: %#", child.Kid , childItem1.text);
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"context 2 is: %#", context);
NSLog(#"major fail %#", [error localizedDescription]);
// abort();
}
}
NSLog(#"saving stuff");
}
// FetchData
- (BOOL)fetchData {
NSLog(#"doing the fetch");
BOOL returnResult = FALSE;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
if (managedObjectContext == nil)
{
NSLog(#"ok making a new managed object context");
managedObjectContext = [(CoreDataStuffAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Parent" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:1];
NSError *error;
NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];
if (mutableFetchResults == nil) {
NSLog(#"Fetching Error");
} else {
[self setParentArray:mutableFetchResults];
returnResult = TRUE;
NSLog(#"Fetching went well");
}
[mutableFetchResults release];
[fetchRequest release];
return (returnResult);
}
Okay, firstly, I think you have a conceptual problem here because I have never seen the need for an entity with 100 attributes. Most entities have a around a half-dozen attributes and I think the most I've ever seen was around 20.
Core Data is first and foremost an object graph management system with persistence tossed in as an option. It is intended to implement the model layer of a Model-View-Controller(MVC) design. As such, Core Data is primarily about modeling data not storing it.
Entities are intended to represent some real-world object, condition or event. There aren't a lot of real-world things that have a 100 attributes. E.g. You want to make a detailed model of a person. You want things like first name, last name, address(with attributes for each address component), driver's license# and date of issue, place of employment with address, social security number etc. If you tried to cram all that into one Person entity you could end up with a dozens of attributes. However, if you look closely at the data you are modeling and the relationships within the data, you would note that in the real world, addresses, driver's license, places of employment etc are not actually attributes of real people but rather other real-objects related to real people. Therefore, the best approach would be to break out the attributes for those objects into separate entities and create relationships to the Person entity. This makes model more realistic as well. After all, more than one person can live at the same address or work at the same place.
So, you probably need to start over from scratch and rethink your data model design.
Make sure you understand the difference between entities and managedObjects. Entities are abstract and serve merely to define keys, value types and relationships for managedObjects. Entities are to managedObjects as classes are to instances.
You have two other problems:
(1) You can only use the dot syntax accessor forms e.g parentInfo.ParentToChild.Kid if you have defined custom NSManagedObject subclasses for your entities. Otherwise, you are using generic NSManagedObject instances and must use the key-value methods e.g. [parent setvalue:forKey].
(2) A fetch returns only objects of one entity. So if you have a Parent entity and a Child entity. Each fetch returns instances of either Parent or Child but never both (unless they both inherit from the fetch's entity.)

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