Core Data ignoring validation constraint
| Originator: | atomicbird | ||
| Number: | rdar://10666148 | Date Originated: | 09-Jan-2012 05:38 PM |
| Status: | Duplicate/10014536 | Resolved: | |
| Product: | iOS | Product Version: | 5.0.1 |
| Classification: | Serious Bug | Reproducible: | Always |
09-Jan-2012 05:38 PM Tom Harrington:
'ValidationFail.zip' was successfully uploaded
09-Jan-2012 05:38 PM Tom Harrington:
Summary:
Core Data ignores validation constraints that set a minimum value for a string attribute's length.
Steps to Reproduce:
1. Create a new iOS project that includes Core Data.
2. In the data model editor, create an entity with a string attribute.
3. For the attribute in step 2, add validation constraints for the string's length. Add both minimum and maximum length constraints.
4. In code, create an instance of this entity and an NSString which is too short to pass the minimum length constraint.
5. Call -validateValue:forKey:error: on the instance using the string attribute and the too-short NSString. Validation passes.
6. Set the NSString as the value for the string attribute and call -validateForInsert: on the instance. Again, validation passes.
Expected Results:
Since the attribute has a constraint specifying minimum string length, a string that is too short to pass this test would cause a validation error.
Actual Results:
Validation succeeds. In the test project attached, the Item entity has a string attribute called "name" that has validation constraints giving a minimum length of 3 and a maximum length of 10. I wondered if Xcode's GUI was showing incorrect state so I looked in the data model file and found:
<attribute name="name" optional="YES" attributeType="String" minValueString="3" maxValueString="10" syncable="YES"/>
So that looks OK. If I inspect the constraints in the Xcode debugger however, I get this:
(gdb) [[[[item entity] attributesByName] objectForKey:@"name"] validationPredicates]
<__NSArrayM 0x897bcd0>(
length <= 10
)
The minimum constraint is not present. A second attribute ("style") has only a minimum length constraint, which is also present in the data model but not at run time.
The code used to check on this is as follows, and is included in the attached project.
NSManagedObject *item = [NSEntityDescription insertNewObjectForEntityForName:@"Item" inManagedObjectContext:[self managedObjectContext]];
NSString *tooShortString = @"a";
NSError *validationError;
NSLog(@"Validation predicates for name: %@", [[[[item entity] attributesByName] objectForKey:@"name"] validationPredicates]);
NSLog(@"Validation predicates for style: %@", [[[[item entity] attributesByName] objectForKey:@"style"] validationPredicates]);
validationError = nil;
[item validateValue:&tooShortString forKey:@"name" error:&validationError];
validationError = nil;
[item validateValue:&tooShortString forKey:@"style" error:&validationError];
validationError = nil;
[item validateForInsert:&validationError];
Regression:
Unknown.
Notes:
Mac OS X 10.7.2, Xcode 4.2.1, iOS 5.0.1, results are the same in the simulator and on an iPhone 4s.
[Openradar: Demo code is at http://dl.dropbox.com/u/14191/openradar/10666148/ValidationFail.zip]
14-Feb-2012 12:07 PM Tom Harrington:
FWIW the same problem shows up for decimal fields with min/max values. It's possible to configure both in the model editor but only the max constraint will exist at run time.
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!
Re: May be fixed in Xcode 4.3
I have just tried compiling a Core Data application with string constraints in place, and yes, under Xcode 4.3 the data model has both the minimum and maximum ones, and they are respected when validating properties. A quick check with number constraints has shown that those, too, are correctly loaded and respected by the application.
It does look like Apple has addressed this issue.
May be fixed
I haven't heard from Apple about a fix yet but it looks like Xcode 4.3 takes care of it. I had narrowed it down to the problem being Xcode unexpectedly losing track of the constraint rather than Core Data failing to use it. In preliminary testing with Xcode 4.3 the issue no longer occurs.
...sometimes...
This bug exists for numeric fields as well. You can configure a min and max constraint in the model editor, but only the max limit will exist at run time. Numeric properties of course don't have a regex field, so that's no help. It might be possible to roll your own via userInfo properties, with some custom validation code.
There's a workaround...
Apple confirmed that this is a known bug, but there's a workaround. Instead of using the model editor's min and max length fields, use the regular expression field. Validate against a regexp that matches the number of characters. For my example of requiring 3-10 characters, use "^.{3,10}$" to validate any string in that length. If you want to require non-whitespace characters, use "^\S{3,10}$". Adjust the 3 and the 10 in the regexp to match your requirements. (Thanks to Marcus Zarra for suggesting this).
Core Data ignores minimum length constraint on a string attribute under Mac OS 10.7.2 & Xcode 4.2.1
I am having this exact issue as well.
Core Data ignores minimum length constraint on a string attribute under Mac OS 10.7.2 & Xcode 4.2.1
I confirm that the identical behaviour is observed when a model is loaded into an application run under Mac OS 10.7.2. The minimum length constraint is present in the model file, but not in the model loaded into memory and accessible through the standard Core Data API.