`
dcj3sjt126com
  • 浏览: 1830060 次
  • 性别: 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: Updated for Swift 3

    This book strives to give you clear guidelines for how to get the most out of Core Data while avoiding the pitfalls of this flexible and powerful framework. We start with a simple example app and ...

    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数据验证

    这一段代码具体实现了如何验证输入数据的合法性。

    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 3rd

    What is Core Data? You'll hear a variety of answers to this question: It’s a database! It's SQLite! It's not a database! And so forth. Here's the technical answer: Core Data is an object graph ...

    Core Data by Tutorials v4.0 (Swift 4)

    Core Data by Tutorials v4.0 Core Data by Tutorials v4.0

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

    Core Data by Tutorials v4.0 Core Data by Tutorials v4.0

    Core Data objc

    Core Data objc Core Data objc Core Data objc Core Data objc Core Data objc

    Pro Core Data for IOS

    Fully updated for Xcode 4.2, Pro Core Data for iOS explains how to use the Core Data framework for iOS SDK 5 using Xcode 4.2.

    Data Driven: Harnessing Data and AI to Reinvent Customer Engagement

    The indispensable guide to data-powered marketing from the team behind the data management platform that helps fuel Salesforce―the #1 customer relationship management (CRM) company in the world ...

    EdgeX core data microservice

    The deep dive internal logic of core data in edgex foundry platform.

    验证过的系统备份ov7670_ov2643_ov5640 20150818 2356

    D:\IMG验证过的\marsboard_lcd5inch_video0_csi0_ov2643\armcore_csi03_ov2643_csi11_wv2643\lichee\tools\pack 2015/8/17 12:25 ov2643通 wv2643不通????原因不明 D:\IMG验证过的\marsboard_lcd5inch_...

    Core Data:Apple’s API for Persisting Data on Mac OS X

    Core Data:Apple’s API for Persisting Data on Mac OS X,介绍mac osx下core data框架。

    Core Data 数据自动封装

    能够十分方便地为 Core Data 数据自动封装CRUD(创建,读取,更新和删除)操作。并且指定排序的域,可以自动为Core Data 数据加上按照这个域的排序操作。 Demo的演示了CRUD操作以及索引排序操作,比如自动为小编...

    Core Data例子3

    Core Data允许用户使用代表实体和实体间关系的高层对象来操作数据。它也可以管理串行化的数据,提供对象生存期管理与object graph管理,包括存储。Core Data直接与SQLite交互,避免开发者使用原本的SQL语句

    Core Data例子4

    Core Data允许用户使用代表实体和实体间关系的高层对象来操作数据。它也可以管理串行化的数据,提供对象生存期管理与object graph管理,包括存储。Core Data直接与SQLite交互,避免开发者使用原本的SQL语句

    Core Data例子2

    Core Data允许用户使用代表实体和实体间关系的高层对象来操作数据。它也可以管理串行化的数据,提供对象生存期管理与object graph管理,包括存储。Core Data直接与SQLite交互,避免开发者使用原本的SQL语句

    CPU验证,core验证,processor 验证

    CPU验证,core验证,processor 验证

    Mastering Core Data With Swift mobi

    Mastering Core Data With Swift 英文mobi 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除

    Core.Data.Updated.for.Swift.3

    Core.Data.Updated.for.Swift.3 學習 Swift 3 Core Data 必看書籍

Global site tag (gtag.js) - Google Analytics