• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Core Data : calling validation in awakeFromInsert problem ?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Core Data : calling validation in awakeFromInsert problem ?


  • Subject: Re: Core Data : calling validation in awakeFromInsert problem ?
  • From: mmalcolm crawford <email@hidden>
  • Date: Mon, 5 Sep 2005 12:07:49 -0700


On Sep 5, 2005, at 9:42 AM, Eric Morand wrote:
I have a managed object with one property named "name". This property is a string. I want this property to be unique in the managed context of the object, so I've implemented "validateName..." method in my managed object subclass (see code below).
Next, I want new objects inserted into the context to have a name set to a validated one (that means : unique). So I have implemented "awakeFromInsert..." method in my subclass that set the name property to a valid one.
[...]
Here is the code for my custom class (implementation only, there is nothing of interest in the header) :
]...]
- (void)awakeFromInsert
{
[...]
NSString * validName = nil;
NSString * defaultName = [NSString stringWithString:@"TestObjectName"];


    validName = defaultName;

    int index = 0;

while ( ![self validateValue:&validName forKey:@"name" error:nil] )
{
index++;


validName = [defaultName stringByAppendingFormat:@" (%d)", index];
}


    [self setName:validName];
}

- (BOOL)validateName: (id *)valueRef error:(NSError **)outError
{
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"name == %@", *valueRef];


NSEntityDescription * entityDescription = [NSEntityDescription entityForName:@"TestObject" inManagedObjectContext:[self managedObjectContext]];
NSFetchRequest * fetchRequest = [[[NSFetchRequest alloc] init] autorelease];


    [fetchRequest setEntity:entityDescription];
    [fetchRequest setPredicate:predicate];

NSArray * results = [[self managedObjectContext] executeFetchRequest:fetchRequest error:nil];

return ( [results count] < 1 ) || ( [results objectAtIndex:0] == self );
}


@end

I'm using a simple interface to test the insertion process : in fact it is the standard interface created automatically when alt- dragging the object from Xcode to IB - one table view, 3 buttons (Fetch, Add, Remove), a text field to enter name and a search field. Then, the problems begin : when I click on the add button, TWO objects are added to the table view !

I'm not sure if this is a bug (I'll follow up) but it's because you're executing a fetch (whose results will include self) before the insertion has completed. You can sidestep this by setting the name after awakeFromInsert:

- (void)awakeFromInsert
{
[super awakeFromInsert];
[self performSelector:@selector(setUniqueName) withObject:nil afterDelay:0];
}


There are several issues with the remainder of the awakeFromInsert code (now moved to the new method) and the validation method:


- (void)setUniqueName
{
NSString * defaultName = @"TestObjectName"; // no need for stringWithString:
NSString * validName = defaultName; // no need for two assignments
int index = 0;
while ( ![self validateValue:&validName forKey:@"name" error:nil] )
{
index++;
validName = [defaultName stringByAppendingFormat:@" (%d)", index];
}
[self setName:validName];
}



- (BOOL)validateName: (id *)valueRef error:(NSError **)outError
{
/*
Check (SELF != %@) in fetch; use 'LIKE' not '==' for string comparison
*/
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"(SELF != %@) AND (name LIKE %@)", self, *valueRef];
NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init];
/*
Use self's entity -- no need to use NSEntityDescription method to retrieve (also avoids hard-wiring entity name)
*/
[fetchRequest setEntity:[self entity]];
[fetchRequest setPredicate:predicate];


/*
Should check for error
*/
NSArray * results = [[self managedObjectContext] executeFetchRequest:fetchRequest error:nil];


    [fetchRequest release];

    return ( [results count] < 1 );
}



And do you think I'm using the right process to validate my name property and mak sure my object are inserted with valid name ?

This approach will be very inefficient for anything but data sets where there is little likelihood of name collisions -- you have to do an additional fetch for every collision. It's not clear what your goal is here. If you're simply wanting to set temporary distinct names (like window titles) for small numbers of objects, this would probably be OK. If these will be permanent values for an ever- increasing number of objects, then you'll need a different approach...


mmalc

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Follow-Ups:
    • Re: Core Data : calling validation in awakeFromInsert problem ?
      • From: guillaume garcera <email@hidden>
    • Re: Core Data : calling validation in awakeFromInsert problem ?
      • From: Eric Morand <email@hidden>
References: 
 >Core Data : calling validation in awakeFromInsert problem ? (From: Eric Morand <email@hidden>)

  • Prev by Date: [cocoa scripting] getting script class attribute name
  • Next by Date: [Moderator] Re: Beta Testers needed
  • Previous by thread: Core Data : calling validation in awakeFromInsert problem ?
  • Next by thread: Re: Core Data : calling validation in awakeFromInsert problem ?
  • Index(es):
    • Date
    • Thread