`
dcj3sjt126com
  • 浏览: 1871723 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Core Data浅谈系列之六 : 验证用户输入

    博客分类:
  • IOS
阅读更多

在做Web开发时,需要谨记的一条原则是“绝不要相信用户的任何输入”(参见《Essential PHP Security》)。

与网页上的表单提交类似,做客户端开发时也应该考虑用户输入,比如可以为UITextField设置代理处理用户实时输入的内容,也可以读取完用户输入再做检查,或者是NSManagedObject的验证功能
 
比如,我们可以在Player的实现里提供验证函数: 
  1. #define PLAYER_ERROR_DOMAIN @"PLAYER_ERROR_DOMAIN"  
  2.   
  3. enum _playerErrorCode {  
  4.     PLAYER_INVALID_AGE_CODE = 0,  
  5.     PLAYER_INVALID_NAME_CODE,  
  6.     PLAYER_INVALID_CODE  
  7. };  
  8. typedef enum _playerErrorCode PlayerErrorCode;  
  1. @implementation Player  
  2.   
  3. @dynamic age;  
  4. @dynamic name;  
  5. @dynamic team;  
  6.   
  7. - (BOOL)validateName:(id *)ioValue error:(NSError **)outError  
  8. {  
  9.     NSString *playerName = *ioValue;  
  10.     playerName = [playerName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];  
  11.     if (!playerName || [playerName length] == 0) {  
  12.         if (outError) {  
  13.             NSString *errorStr = @"Player's name should not be empty.";  
  14.             NSDictionary *userInfoDict = @{ NSLocalizedDescriptionKey : errorStr };  
  15.             NSError *error = [[NSError alloc] initWithDomain:PLAYER_ERROR_DOMAIN  
  16.                                                         code:PLAYER_INVALID_NAME_CODE  
  17.                                                     userInfo:userInfoDict];  
  18.             *outError = error;  
  19.         }  
  20.         return NO;  
  21.     }  
  22.   
  23.     return YES;  
  24. }  
  25.   
  26. @end  
当context在执行save动作时,这些属性验证函数会得到调用,如果验证函数返回NO,则save动作会失败:
 
[plain] view plaincopy
  1. 2013-01-17 22:36:42.393 cdNBA[673:c07] Error Error Domain=PLAYER_ERROR_DOMAIN Code=1 "Player's name should not be empty." UserInfo=0x827e380 {NSLocalizedDescription=Player's name should not be empty.}, Player's name should not be empty.  
当然,我们绝对不会希望异常发生在这个位置,让程序直接挂掉 —— 这里只是一个Demo。
因为只有在保存context时才会调用验证函数,为了不让程序挂在这里,我们可以提前进行验证: 
  1. NSString *name = self.nameTextField.text;  
  2. NSError *error = NULL;  
  3. [playerObject validateValue:&name forKey:@"name" error:&error];  
  4. if (error) {  
  5.     NSLog(@"%@\n", [error localizedDescription]);  
  6. }  
除了name,我们还可能验证age或者其它属性,同样地可以写相应的属性验证函数。但是,有些属性的验证是需要结合在一起作为判断条件的。这种情况下,我们可以利用属性间的结合验证:
  1. - (BOOL)validateForInsert:(NSError **)outError  
  2. {  
  3.     BOOL valid = [super validateForInsert:outError];  
  4.       
  5.     NSString *playerName = self.name;  
  6.     if (!playerName || [playerName length] == 0) {  
  7.         if (outError) {  
  8.             NSString *errorStr = @"Player's name should not be empty.";  
  9.             NSDictionary *userInfoDict = @{ NSLocalizedDescriptionKey : errorStr };  
  10.             NSError *error = [[NSError alloc] initWithDomain:PLAYER_ERROR_DOMAIN  
  11.                                                         code:PLAYER_INVALID_NAME_CODE  
  12.                                                     userInfo:userInfoDict];  
  13.             *outError = [self errorFromOriginalError:error error:nil];  
  14.         }  
  15.         valid = NO;  
  16.     }  
  17.       
  18.     NSInteger playerAge = [self.age integerValue];  
  19.     if (!self.age || (playerAge < 16 || playerAge > 50)) {  
  20.         if (outError) {  
  21.             NSString *errorStr = @"Player's age should be in [16, 50].";  
  22.             NSDictionary *userInfoDict = @{ NSLocalizedDescriptionKey : errorStr };  
  23.             NSError *error = [[NSError alloc] initWithDomain:PLAYER_ERROR_DOMAIN  
  24.                                                         code:PLAYER_INVALID_AGE_CODE  
  25.                                                     userInfo:userInfoDict];  
  26.             *outError = [self errorFromOriginalError:*outError error:error];  
  27.         }  
  28.         valid = NO;  
  29.     }  
  30.       
  31.     return valid;  
  32. }  
  33.   
  34. // Modified from https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdValidation.html  
  35. //  
  36. - (NSError *)errorFromOriginalError:(NSError *)originalError error:(NSError *)secondError  
  37. {  
  38.     NSMutableDictionary *userInfo = [NSMutableDictionarydictionary];  
  39.       
  40.     NSMutableArray *errors = [NSMutableArrayarray];  
  41.     if (secondError) {  
  42.         [errors addObject:secondError];  
  43.     }  
  44.       
  45.     if ([originalError code] == NSValidationMultipleErrorsError) {  
  46.         [userInfo addEntriesFromDictionary:[originalError userInfo]];  
  47.         [errors addObjectsFromArray:[userInfo objectForKey:NSDetailedErrorsKey]];  
  48.     } else {  
  49.         [errors addObject:originalError];  
  50.     }  
  51.       
  52.     [userInfo setObject:errors forKey:NSDetailedErrorsKey];  
  53.       
  54.     return [NSErrorerrorWithDomain:NSCocoaErrorDomain  
  55.                                code:NSValidationMultipleErrorsError  
  56.                            userInfo:userInfo];  
  57. }  
由于存在多种属性的验证,所以提供了错误信息的连接函数,这有点类似php中我们经常会写的字符串连接点符号:
  1. error = "Invalid username or password.";  
  2. error .= "Invalid token.";  
NSManagedObject提供了三个函数用户在插入、修改、删除之前进行验证,分别是上面的validateForInsert,以及validateForUpdate和validateForDelete。
这次如果name和age都为空,则会输出如下错误信息: 
[plain] view plaincopy
  1. 2013-01-17 23:42:03.979 cdNBA[1064:c07] Error Error Domain=NSCocoaErrorDomain Code=1560 "The operation couldn’t be completed. (Cocoa error 1560.)" UserInfo=0x111394b0 {NSDetailedErrors=(  
  2.     "Error Domain=PLAYER_ERROR_DOMAIN Code=0 \"Player's age should be in [16, 50].\" UserInfo=0x1112fbf0 {NSLocalizedDescription=Player's age should be in [16, 50].}",  
  3.     "Error Domain=PLAYER_ERROR_DOMAIN Code=1 \"Player's name should not be empty.\" UserInfo=0x11139430 {NSLocalizedDescription=Player's name should not be empty.}"  
  4. )}, The operation couldn’t be completed. (Cocoa error 1560.)  
上面只是简单地对name和age进行是否为空的判定,实际操作还需要判断其它条件。比如还可以判断该球员是否已经存在,或者是之前提到的球队同名问题。
 
假设我们输入了合法的数据,创建了一名球员的信息,结果返回到上一级视图发现没有得到展现。对于这种情况,我们可以先很黄很暴力地在viewWillAppear里面重新reload下table,或者通过观察者模式监听相应的消息进行刷新。这里即将讨论的方法是使用NSFetchedResultsController这个类。
分享到:
评论

相关推荐

    Core Data数据验证

    数据验证是确保数据质量的重要环节,特别是在用户输入数据时,防止无效或不合法的数据进入数据库。本节将深入探讨如何在Core Data中实现数据验证。 首先,Core Data的数据模型(xcdatamodel)定义了实体(Entity)...

    Core Data: Updated for Swift 3

    ### Core Data: 更新至 Swift 3 #### 一、引言与Swift的融合 本书旨在为读者提供关于如何最大限度地利用Core Data框架的同时避免潜在陷阱的清晰指导。本书假设读者已经熟悉Swift语言及其iOS开发环境,但对于无论是...

    Core.Data.in.Swift.Data.Storage.and.Management.for.iOS.and.OSX

    Core Data is intricate, powerful, and necessary. Discover the powerful capabilities integrated into Core Data, and how to use Core Data in your iOS and OS X projects. All examples are current for OS X...

    Core Data by Tutorials v4.0 (Swift 4)

    《Core Data by Tutorials v4.0 (Swift 4)》是针对苹果开发平台的一款深入讲解Core Data技术的教程,特别适用于使用Swift 4编程语言的开发者。Core Data是Apple提供的一项强大的数据管理框架,它简化了应用程序的...

    Data Analytics with Hadoop: An Introduction for Data Scientists

    "Data Analytics with Hadoop: An Introduction for Data Scientists" ISBN: 1491913703 | 2016 | PDF | 288 pages | 7 MB Ready to use statistical and machine-learning techniques across large data sets? ...

    Core Data by Tutorials v4.0 Source Code (Swift4)

    - **异步操作**:Core Data支持异步操作,提高了性能和用户体验,特别是在处理大量数据时。 - **故障延迟加载(Faulting and Lazy Fetching)**:Core Data通过故障机制来优化内存使用,只有当需要时才加载实体的...

    Pro Core Data for IOS

    本书《Pro Core Data for iOS》以完全更新的形式针对Xcode 4.2版本,涵盖了iOS SDK 5环境下Core Data框架的使用方法。Core Data是苹果公司推出的数据存储和检索技术,它对于开发者来说易于上手,但深入掌握却颇具...

    Core Data by Tutorials

    这本书特别为iOS 8和Xcode环境编写,提供了系统性地从零开始构建Core Data应用程序的知识,以及如何处理Core Data堆栈、数据的保存与检索、数据验证以及如何提高性能和进行单元测试。 知识点一:Core Data基础介绍 ...

    ABAP Core Data Services .pdf

    ### ABAP Core Data Services (CDS):SAP最新技术详解 #### 一、引言 随着企业数据处理需求的不断增长以及业务复杂性的提升,SAP推出了一种全新的技术——ABAP Core Data Services(简称CDS),旨在帮助开发者更...

    Core Data in Objective-C Data Storage and Management for iOS and OS X(3rd)

    5. **性能优化技巧**:提供了一系列提高Core Data性能的方法,包括缓存策略、批量操作等。 6. **高级主题**:包括错误处理、版本控制、实时同步等高级特性。 7. **实战案例分析**:通过具体的项目案例来展示如何在...

    表单验证只能输入数字中文源码

    在IT行业中,表单验证是前端开发中的一个重要环节,它确保用户输入的数据符合特定的格式和规则,从而提高数据的准确性和安全性。本资源提供的"表单验证只能输入数字中文源码"是一个针对JSP(JavaServer Pages)开发...

    Core Data - Florian Kugler Daniel Eggert

    ### Core Data - Florian Kugler Daniel Eggert #### 一、引言与Swift语言的注意事项 本书由Florian Kugler和Daniel Eggert撰写,旨在为开发者提供一份详尽的Core Data指南。作为iOS开发中不可或缺的一部分,Core ...

    Core.Data.Updated.for.Swift.3

    本书《Core.Data.Updated.for.Swift.3》是关于学习使用Swift 3进行Core Data开发的指导书。Core Data是苹果公司提供的一个框架,用于管理应用程序数据模型对象的生命周期,它简化了数据持久化过程。在本书的介绍中,...

    Core Data objc中国(最新版已对应Swift4)花钱买的包含pdf,mobi,epub格式

    总之,《Core Data》这本书全面覆盖了从基础到高级的Core Data使用技巧,适合不同层次的iOS开发者阅读,无论你是初学者还是经验丰富的专业人士,都能从中获益匪浅。通过系统的学习和实践,你将能够更好地利用Core ...

    Core Data 示例源码 操作xml归档

    Core Data是苹果开发框架中的一个重要组成部分,主要用于管理应用程序的数据模型。这个“Core Data 示例源码 操作xml归档”是一个示例项目,旨在演示如何在OS X平台上利用Core Data框架来处理XML档案。通过这个教程...

    Core Data 编程指南

    9. 验证和转换:Core Data允许开发者定义数据验证规则,以确保输入的数据符合预期格式。此外,还可以自定义数据转换逻辑,以适应不同的数据源和格式。 总之,Core Data是Apple平台开发中不可或缺的一部分,它简化了...

    Core Data By Tutorials

    4. **Core Data堆栈(The Core Data Stack)**:Core Data堆栈是指一系列协同工作的对象,它们共同完成了数据的存储和检索。这包括托管对象模型(Managed Object Model)、持久化存储(Persistent Store)和持久化...

    Core Data iOS Essentials

    ### Core Data iOS Essentials #### 一、概述 《Core Data iOS Essentials》是一本关于iOS应用程序开发的专业书籍,主要聚焦于如何使用Core Data框架来管理数据。本书由B. M. Harwani撰写,并由Packt Publishing...

Global site tag (gtag.js) - Google Analytics