coredata学习总结(十二)

Object Validation

cocoa提供了一个基本的model值验证的机制。但是它要求你必须为所有想用的地方写代码。core data,另一方面允许你把验证逻辑放到managed 对象model中并且书写验证逻辑。

How Validation Works in Core Data

如何验证是一个model方案。当被验证的是一个用户接口或者controller级别的方案时。例如,一个text field绑定的值可能设置了validates immediately选项。

一个内存中的对象可能短期内变为不一致的。只有在save操作或者request的时候,验证约束才会提供。有时候,需要在数据有变化时就验证并且即刻报告错误。如果managed 对象被要求总是有效的状态,会强制用户的特定流程。

Implementing Custom Property-Level Validation

NSKeyValueCoding协议指定了validateValue:forKey:error:方法来提供对于验证方法的一般支持。

In the method implementation, you check the proposed new value, and if it does not fit your constraints, you returnNO. If the error parameter is notnull, you also create an NSError object that describes the problem, as illustrated in the following example. The example validates that the age value is greater than zero. If it is not, an error is returned.

  1. - (BOOL)validateAge:(id*)ioValueerror:(NSError**)outError
  2. {
  3. if (*ioValue== nil) {
  4. return YES;
  5. }
  6. if ([*ioValuefloatValue] <=0.0) {
  7. if (outError== NULL) {
  8. return NO;
  9. }
  10. NSString *errorStr= NSLocalizedStringFromTable(@"Age must be greater than zero",@"Employee", @"validation: zero age error");
  11. NSDictionary *userInfoDict = @{NSLocalizedDescriptionKey:errorStr};
  12. NSError *error= [[NSError alloc] initWithDomain:EMPLOYEE_ERROR_DOMAINcode:PERSON_INVALID_AGE_CODE userInfo:userInfoDict];
  13. *outError= error;
  14. return NO;
  15. } else{
  16. return YES;
  17. }
  18. }
  1. func validateAge(value:AutoreleasingUnsafeMutablePointer<AnyObject?>)throws {
  2. if value ==nil {
  3. return
  4. }
  5.  
  6. let valueNumber =value.memory as!NSNumber
  7. if valueNumber.floatValue >0.0 {
  8. return
  9. }
  10. let errorStr =NSLocalizedString("Age must be greater than zero",tableName: "Employee", comment: "validation: zero age error")
  11. let userInfoDict = [NSLocalizedDescriptionKey:errorStr]
  12. let error =NSError(domain: "EMPLOYEE_ERROR_DOMAIN",code: 1123, userInfo:userInfoDict)
  13. throw error
  14. }

Implementing Custom Interproperty Validation

一个对象的所有独立的属性可能是valid但是不同属性值的组合可能就是invalid的。例如,应用程序存储了人的age和是否有驾照。对于一个person对象,12可能是一个有效的age属性值,yes是一个有效的hasDrivingLicense值。但是这两个条件一起可能就是invalid的值。

NSManagedObject 提供了额外的机会来验证-更新,插入,删除-通过方法validateFor…例如validateForUpdate:.如果你实现自定义的验证方法,你应当首先调用super class的实现来确保单独的属性验证被触发了。如果superclass的实现失败,那么你就可以做如下的操作:

  • 返回no和superclass实现的error
  • 继续执行验证,查找矛盾的合并值。

如果你继续执行验证,确保在你逻辑中的任何值不是本身invalid导致的错误。例如,假设你用了一个值为0的属性作为除数,但是值却是要求大于0的。如果你进一步发现了验证错误,你必须把她们同现存的错误合并起来并且返回一个multiple errors error”作为描述。

下面的例子展示了一个验证方法的实现。person实体有两个属性,birthday和hasdrivinglicense。约束是person小于16岁的不能有驾照。在validateForInsert:validateForUpdate:,中这个约束都做了检查。因此验证逻辑就单独放在了一个方法中。

Listing 14-1Interproperty validation for a Person entity

  1. - (BOOL)validateForInsert:(NSError**)error
  2. {
  3. BOOL propertiesValid= [super validateForInsert:error];
  4. // could stop here if invalid
  5. BOOL consistencyValid= [self validateConsistency:error];
  6. return (propertiesValid&& consistencyValid);
  7. }
  8. - (BOOL)validateForUpdate:(NSError**)error
  9. {
  10. BOOL propertiesValid= [super validateForUpdate:error];
  11. // could stop here if invalid
  12. BOOL consistencyValid= [self validateConsistency:error];
  13. return (propertiesValid&& consistencyValid);
  14. }
  15. - (BOOL)validateConsistency:(NSError**)error
  16. {
  17. static NSCalendar*gregorianCalendar;
  18. NSDate *myBirthday= [self birthday];
  19. if (myBirthday== nil) {
  20. return YES;
  21. }
  22. if ([[selfhasDrivingLicense] boolValue] == NO) {
  23. return YES;
  24. }
  25. if (gregorianCalendar== nil) {
  26. gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
  27. }
  28. NSDateComponents *components = [gregorianCalendar components:NSCalendarUnitYearfromDate:myBirthday toDate:[NSDate date] options:0];
  29. NSInteger years= [componentsyear];
  30. if (years>= 16) {
  31. return YES;
  32. }
  33. if (error== NULL) {
  34. //don't create an error if none was requested
  35. return NO;
  36. }
  37. NSBundle *myBundle= [NSBundle bundleForClass:[self class]];
  38. NSString *drivingAgeErrorString= [myBundle localizedStringForKey:@"TooYoungToDriveError" value:@"Person is too young to have a driving license."table:@"PersonErrorStrings"];
  39. NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
  40. [userInfosetObject:drivingAgeErrorString forKey:NSLocalizedFailureReasonErrorKey];
  41. [userInfosetObject:self forKey:NSValidationObjectErrorKey];
  42. NSError *drivingAgeError= [NSError errorWithDomain:EMPLOYEE_ERROR_DOMAIN code:NSManagedObjectValidationError userInfo:userInfo];
  43. if (*error== nil) { // if there was no previous error, return the new error
  44. *error= drivingAgeError;
  45. } else{ // if there was a previous error, combine it with the existing one
  46. *error= [self errorFromOriginalError:*errorerror:drivingAgeError];
  47. }
  48. return NO;
  49. }
  1. override funcvalidateForInsert() throws {
  2. try super.validateForInsert()
  3. try validateConsistency()
  4. }
  5. override funcvalidateForUpdate() throws {
  6. try super.validateForUpdate()
  7. try validateConsistency()
  8. }
  9. func validateConsistency()throws {
  10. guard letmyBirthday = birthday else {
  11. return
  12. }
  13. if !hasDrivingLicense {
  14. return
  15. }
  16.  
  17. let gregorianCalendar =NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
  18.  
  19. let components =gregorianCalendar.components(.Year,fromDate: myBirthday, toDate: NSDate(), options:.WrapComponents)
  20. if components.year >=16 {
  21. return
  22. }
  23.  
  24. let errString ="Person is too young to have a driving license."
  25. let userInfo = [NSLocalizedFailureReasonErrorKey:errString, NSValidationObjectErrorKey:self]
  26. let error =NSError(domain: "EMPLOYEE_ERROR_DOMAIN",code: 1123, userInfo:userInfo)
  27. throw error
  28. }

Combining Validation Errors

如果在一个操作中出现了多个验证失败,就可以通过NSValidationMultipleErrorsError来创建和返回一个nserror对象。通过NSDetailedErrorsKey将这些错误添加到了数组中。

注意:合并错误目前swift不支持

Listing 14-2A method for combining two errors into a single multiple errors error

  1. - (NSError*)errorFromOriginalError:(NSError*)originalErrorerror:(NSError*)secondError
  2. {
  3. NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
  4. NSMutableArray *errors = [NSMutableArrayarrayWithObject:secondError];
  5. if ([originalErrorcode] == NSValidationMultipleErrorsError) {
  6. [userInfoaddEntriesFromDictionary:[originalErroruserInfo]];
  7. [errorsaddObjectsFromArray:[userInfoobjectForKey:NSDetailedErrorsKey]];
  8. } else{
  9. [errorsaddObject:originalError];
  10. }
  11. [userInfosetObject:errors forKey:NSDetailedErrorsKey];
  12. return [NSErrorerrorWithDomain:NSCocoaErrorDomaincode:NSValidationMultipleErrorsErroruserInfo:userInfo];
  13. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值