KVC and setValue: forUndefinedKey: method, kvcsetvalue

Source: Internet
Author: User

KVC and setValue: forUndefinedKey: method, kvcsetvalue

During actual development and application, the number of dictionary keys constructed from external data is usually higher than the number of attributes in the Custom Data Model.

For example, obtaining data in JSON format from the outside contains five keys, as shown below:

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

The corresponding model only contains three attributes:

/** City name */@ property (copy, nonatomic) NSString * cityname;/** minimum temperature */@ property (copy, nonatomic) NSNumber * tem1; /** maximum temperature */@ property (copy, nonatomic) NSNumber * tem2;

The sample code is as follows:

Controller ViewController. m:

# Import "ViewController. h "# import" Weather. h "@ interface ViewController () @ end @ implementation ViewController-(void) viewDidLoad {[super viewDidLoad]; // read external data in JSON format NSURL * url = [[NSBundle mainBundle] URLForResource: @ "weather" withExtension: @ "json"]; NSData * data = [NSData dataWithContentsOfURL: url]; NSDictionary * dict = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableContainers error: NULL]; // data model instance Weather * w = [Weather weatherWithDictionary: dict]; NSLog (@ "% @", w) ;}@ end

Model class Weather. h:

# Import <Foundation/Foundation. h> @ interface Weather: NSObject/** city name */@ property (copy, nonatomic) NSString * cityname;/** minimum temperature */@ property (copy, nonatomic) NSNumber * tem1;/** maximum temperature */@ property (copy, nonatomic) NSNumber * tem2;-(instancetype) initWithDictionary :( NSDictionary *) dict; + (instancetype) weatherWithDictionary :( NSDictionary *) dict; @ end

Model class 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


If you run the program, the following error message is reported:

*** 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

When setValuesForKeysWithDictionary: method is used, the system will automatically call setValue: forUndefinedKey: This method for attributes that are missing in the data model and cannot be paired with any keys, the default implementation of this method will cause an NSUndefinedKeyExceptiony exception.

If you want the program to run without causing any exception information and work properly, you can have the data model class override setValue: forUndefinedKey: Method to override the default implementation, in addition, two parameters of this method can be used to obtain the key value that cannot be paired.

The modified model Weather. m:

# Import "Weather. h" @ implementation Weather-(instancetype) initWithDictionary :( NSDictionary *) dict {self = [super init]; if (nil! = Self) {[self setValuesForKeysWithDictionary: dict];} return self;} // rewrite setValue: forUndefinedKey: method-(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

In this example, override setValue: forUndefinedKey: method, but do not perform any substantive operations on key values that are not paired to ignore them. Of course, you can also process the key value in the method body.

After the modification is completed, the program output is as follows:

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


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.