KVC與setValue:forUndefinedKey:方法,kvcsetvalue

來源:互聯網
上載者:User

KVC與setValue:forUndefinedKey:方法,kvcsetvalue

在實際開發及應用過程中,經常會遇到通過外部資料構造的字典的鍵要多於自訂資料模型中屬性的個數的情況。

例如:從外部獲得JSON格式的資料包含5個鍵,如下所示:

{    "cityname" : "beijing",    "state1" : "0",    "state2" : "1",    "tem1" : "25",    "tem2" : "14",}

而與之對應的模型只包含3個屬性:

/** 城市名 */@property (copy, nonatomic) NSString *cityname;/** 最低溫度 */@property (copy, nonatomic) NSNumber *tem1;/** 最高溫度 */@property (copy, nonatomic) NSNumber *tem2;

整個樣本程式的代碼如下:

控制器ViewController.m:

#import "ViewController.h"#import "Weather.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];        // 讀取JSON格式的外部資料    NSURL *url = [[NSBundle mainBundle] URLForResource:@"weather" withExtension:@"json"];    NSData *data = [NSData dataWithContentsOfURL:url];    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:NULL];    // 資料模型執行個體    Weather *w = [Weather weatherWithDictionary:dict];    NSLog(@"%@", w);}@end

模型類Weather.h:

#import <Foundation/Foundation.h>@interface Weather : NSObject/** 城市名 */@property (copy, nonatomic) NSString *cityname;/** 最低溫度 */@property (copy, nonatomic) NSNumber *tem1;/** 最高溫度 */@property (copy, nonatomic) NSNumber *tem2;- (instancetype)initWithDictionary:(NSDictionary *)dict;+ (instancetype)weatherWithDictionary:(NSDictionary *)dict;@end

模型類Weather.m:

 

#import "Weather.h"@implementation Weather- (instancetype)initWithDictionary:(NSDictionary *)dict {    self = [super init];    if (nil != self) {        [self setValuesForKeysWithDictionary:dict];    }    return self;}+ (instancetype)weatherWithDictionary:(NSDictionary *)dict {    return [[self alloc] initWithDictionary:dict];}- (NSString *)description {    return [NSString stringWithFormat:@"[cityname, tem1, tem2] = [%@, %@, %@]", self.cityname, self.tem1, self.tem2];}@end

 

此時,如果運行程式,會報告以下錯誤資訊:

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key state1.'*** First throw call stack:(0   CoreFoundation                      0x000000010e158c65 __exceptionPreprocess + 1651   libobjc.A.dylib                     0x000000010ddefbb7 objc_exception_throw + 452   CoreFoundation                      0x000000010e1588a9 -[NSException raise] + 93   Foundation                          0x000000010d984b53 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 2594   Foundation                          0x000000010d9c6fad -[NSObject(NSKeyValueCoding) setValuesForKeysWithDictionary:] + 2615   2015-05-05-setValueforUndefinedKey  0x000000010d8b94bd -[Weather initWithDictionary:] + 1416   2015-05-05-setValueforUndefinedKey  0x000000010d8b9557 +[Weather weatherWithDictionary:] + 877   2015-05-05-setValueforUndefinedKey  0x000000010d8b9925 -[ViewController viewDidLoad] + 2778   UIKit                               0x000000010e683210 -[UIViewController loadViewIfRequired] + 7389   UIKit                               0x000000010e68340e -[UIViewController view] + 2710  UIKit                               0x000000010e59e2c9 -[UIWindow addRootViewControllerViewIfPossible] + 5811  UIKit                               0x000000010e59e68f -[UIWindow _setHidden:forced:] + 24712  UIKit                               0x000000011bb4a175 -[UIWindowAccessibility _orderFrontWithoutMakingKey] + 6813  UIKit                               0x000000010e5aae21 -[UIWindow makeKeyAndVisible] + 4214  UIKit                               0x000000010e54e457 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 273215  UIKit                               0x000000010e5511de -[UIApplication _runWithMainScene:transitionContext:completion:] + 134916  UIKit                               0x000000010e5500d5 -[UIApplication workspaceDidEndTransaction:] + 17917  FrontBoardServices                  0x0000000110d575e5 __31-[FBSSerialQueue performAsync:]_block_invoke_2 + 2118  CoreFoundation                      0x000000010e08c41c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 1219  CoreFoundation                      0x000000010e082165 __CFRunLoopDoBlocks + 34120  CoreFoundation                      0x000000010e081f25 __CFRunLoopRun + 238921  CoreFoundation                      0x000000010e081366 CFRunLoopRunSpecific + 47022  UIKit                               0x000000010e54fb42 -[UIApplication _run] + 41323  UIKit                               0x000000010e552900 UIApplicationMain + 128224  2015-05-05-setValueforUndefinedKey  0x000000010d8b9c7f main + 11125  libdyld.dylib                       0x0000000110727145 start + 126  ???                                 0x0000000000000001 0x0 + 1)libc++abi.dylib: terminating with uncaught exception of type NSException

當使用setValuesForKeysWithDictionary:方法時,對於資料模型中缺少的、不能與任何鍵配對的屬性的時候,系統會自動調用setValue:forUndefinedKey:這個方法,該方法預設的實現會引發一個NSUndefinedKeyExceptiony異常。

如果想要程式在運行過程中不引發任何異常資訊且正常工作,可以讓資料模型類重寫setValue:forUndefinedKey:方法以覆蓋預設實現,而且可以通過這個方法的兩個參數獲得無法配對索引值。

修改後的模型Weather.m:

#import "Weather.h"@implementation Weather- (instancetype)initWithDictionary:(NSDictionary *)dict {    self = [super init];    if (nil != self) {        [self setValuesForKeysWithDictionary:dict];    }    return self;}// 重寫setValue:forUndefinedKey:方法- (void)setValue:(id)value forUndefinedKey:(NSString *)key {    NSLog(@"key = %@, value = %@", key, value);}+ (instancetype)weatherWithDictionary:(NSDictionary *)dict {    return [[self alloc] initWithDictionary:dict];}- (NSString *)description {    return [NSString stringWithFormat:@"[cityname, tem1, tem2] = [%@, %@, %@]", self.cityname, self.tem1, self.tem2];}@end

本例中,重寫setValue:forUndefinedKey:方法但不對任何未能配對的索引值做任何實質性操作以忽略它們。當然,也可以在方法體中對索引值進行處理。

修改完畢後,運行程式輸出如下:

key = state1, value = 0key = state2, value = 1[cityname, tem1, tem2] = [beijing, 25, 14]

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.