iOS Development Runtime Learning Five: KVC and KVO, using runtime to implement dictionary-to-model

Source: Internet
Author: User

One: KVC and KVO's study

#import "StatusItem.h"/* 1: Summary: KVC Assignment: 1:setvaluesforkeyswithdictionary Implementation principle: Traverse the dictionary, get all key,value values, and then use KVC, Setvaue Forkey to assign value 2: [item setvalue:@ "From Instant Notes" forkey:@ "source"], the underlying implementation of the internal, 1. First go to the model to find there is no setsource, find, direct call assignment [self setsource:@ "from instant note"] 2. To go to the model to find there is no source property, there is a direct access attribute assigned to Source = value 3. Go to the model to find there is no _source attribute, there is, direct access attribute Assignment _source = value 4. Cannot find, will directly error SetValue: Forundefinedkey: The report cannot find the error when the system is not found will call this method, error-(void) SetValue: (ID) value Forundefinedkey: (NSString *) Key can override this method to change the key value 3:KVC Four methods: use KVC to access member variables and properties, Setvalue,value as attribute values, forkey,key as property names, Forkeypath as key-value paths, for example in model with the following attribute definitions: @property (    Nonatomic, strong) BankAccount *account;  KeyPath: [Zhangsan setvalue:@150 forkeypath:@ "Account.balance"]; -(ID) Valueforkey: (NSString *) key; -(ID) Valueforkeypath: (NSString *) KeyPath; -(void) SetValue: (ID) value Forkey: (NSString *) key;  -(void) SetValue: (ID) value Forkeypath: (NSString *) KeyPath; 4:KVO: A key-value observation mechanism for monitoring the change of the value of a property: usage: @interface bankaccount:nsobject @property (nonatomic, assign) Nsinteger balance; @end @interface PersoN:nsobject @property (nonatomic, strong) BankAccount *account; @end @implementation Person-(instancetype) init {...//register observer: [Self.account addobserver:self forkeypath:@ "balance "Options:nskeyvalueobservingoptionnew | Nskeyvalueobservingoptionold Context:nil];  ... }  -(void) Dealloc {//Do not forget Removeobserver [Self.account removeobserver:self forkeypath:@ "balance"];} callback method for property changes:-(void) Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID) object changed: (Nsdictionary *) change Context: (void *) Context {if ([KeyPath isequaltostring:@ "balance"]) {NSLog (@ "balance was%@.", change[ Nskeyvaluechangeoldkey]); NSLog (@ "Balance is%@ now", Change[nskeyvaluechangenewkey]); }} @end-(void) Testkvo {person *zhangsan = [[Person alloc] initwithname:@ "Zhangsan" andbalance:20];//either with the dot syntax or the KVC method Will trigger the callback: ZhangSan.account.balance = 150; [Zhangsan setvalue:@250 forkeypath:@ "Account.balance"];   }*/@interfaceStatusitem () @property (nonatomic,copy) NSString*Hello;@end@implementationStatusitem//The model only holds the most important data, causing the model's properties and dictionaries to not correspond+ (Instancetype) itemwithdict: (Nsdictionary *) dict{Statusitem*item =[[Self alloc] init]; //KVC: Assigns all values in the dictionary to the properties of the model[item setvaluesforkeyswithdictionary:dict]; //get each model attribute, go to the dictionary to take the corresponding value, assign a value to the model//take a value from a dictionary, not necessarily all of it.//mjextension: Dictionary to model Runtime: You can traverse all the attributes in a model//Mjextension: Encapsulates a number of layers//item.pic_urls = dict[@ "Pic_urls"];//item.created_at = dict[@ "Created_at"]; //KVC principle://1. Walk through all keys in the dictionary to find out if there are any corresponding attributes in the model[Dict enumeratekeysandobjectsusingblock:^ (ID_nonnull Key,ID_nonnull value, BOOL *_nonnull stop) {                //2. Go to the model to find out if there are any corresponding attributes KVC//Key:source Value: from Instant notes//[item setvalue:@ "From Instant Notes" forkey:@ "source"][item Setvalue:value Forkey:key];        }]; returnitem;}//Override system Methods? 1. Want to add additional features to the System Method 2. Do not want the system method implementation//This method will be called when the system is not found, error- (void) SetValue: (ID) value Forundefinedkey: (NSString *) key{}@end

Second: Using runtime to implement dictionary to model

#import "ViewController.h"#import "Nsdictionary+property.h"#import "StatusItem.h"#import "nsobject+model.h"@interfaceViewcontroller ()@end/*Summary: 1: Files in the project are stored in the Mainbundle, reading the local information in the project: [[NSBundle Mainbundle] pathforresource:@ "status.plist" oftype:nil]; Get the local path, and then see if the file root node in the project is a dictionary or an array, and read the local path filer:dictionarywithcontentsoffile from there. If you get the path to the network side: Dictionarywithcontentsofurl*/@implementationViewcontroller- (void) viewdidload {[Super viewdidload]; //get file Full pathNSString *filepath = [[NSBundle mainbundle] Pathforresource:@"status.plist"Oftype:nil]; //file Full pathNsdictionary *dict =[Nsdictionary Dictionarywithcontentsoffile:filepath]; //design a model, create a Property Code = = Dict//[dict[@ "user"] createpropertycode]; //Dictionary turn model: kvc,mjextensionStatusitem *item =[Statusitem modelwithdict:dict]; }@end
#import <Foundation/Foundation.h>//  dictionary @interface  nsobject (model) + (Instancetype) modelwithdict: (Nsdictionary *) dict; @end
#import "nsobject+model.h"#import<objc/message.h>/* Summary: Mjextension dictionary to the bottom of the core implementation of the model: runtime implementation of the dictionary to model. 1: Because model all inherit nsobject, so can be extended to the System class write classification, subclass inherits NSObject, that is inherit the method of extension. So the method of model-to-dictionary is considered to extend the method of NSObject writing a classification 2: in the classification if the object method, self refers to the object that calls the method, the class method of self refers to the class that calls the method. Method Design: The class method is simple and rough, directly using the class to call, the dictionary to model method to obtain the transformed model, do not create the object, and will call the method of the class as a parameter into the method (the object method also) 3: Principle: Runtime: According to the model properties, Remove the corresponding value from the dictionary to assign a value of 1 to the model attribute: first get all member variables in the model key parameter meaning://Get the member variable of the class//count: Number of member variable int * type unsigned int count = 0;  Gets an array of member variables Ivar *ivarlist = Class_copyivarlist (self, &count); Note: 1:int *count, this count is of type int * Type, when as a parameter, need to pass in an int * type pointer, the pointer is stored in memory address, that is, the address is passed as a parameter, when the method executes, the system will get *count to assign the value int A = 2; int b = 3; int c = 4; int arr[] = {A,b,c}; int *p = arr; P[0];      NSLog (@ "%d%d", p[0],p[1]);         2: Get class inside Attribute Class_copypropertylist (< #__unsafe_unretained class Cls#>, < #unsigned int *outcount#>) Get all the methods inside the class Class_copymethodlist (< #__unsafe_unretained class Cls#>, < #unsigned int *outcount#>)//Nature: Create Who's Object 3: Gets all the member variables in the model Key,ivar: the member variable begins with an underscore, which is equivalent to an array//Gets the member variable of which class//CouNT: Number of member variables unsigned int count = 0;  Gets an array of member variables Ivar *ivarlist = Class_copyivarlist (self, &count); 4: implementation: Get member Variable name: Ivar_getname (Ivar), belongs to C language string, so UTF8 encoding gets member variable type: ivar_gettypeencoding (Ivar)//Get member variable name NSString * Ivarname = [NSString stringwithutf8string:ivar_getname (Ivar)];  Gets the member variable type nsstring *ivartype = [NSString stringwithutf8string:ivar_gettypeencoding (Ivar)]; Note: 1: string substitution: stringbyreplacingoccurrencesofstring 2: String intercept: Substringfromindex: Includes the index Substringtoindex: does not include the index 3: Prefix: Hasprefix prefixes, Hassuffix: suffix 4: Whether to include a string: containstring 5: String conversion to class:nsclassfromstring://Get classes class Modelclass =  Nsclassfromstring (Ivartype);  Value = [Modelclass modelwithdict:value]; 6: In general, a method to accept the arguments passed in, to determine whether the parameter is empty, nil or null, to assign a value to a value, but also to determine whether the value exists://To the model of the property assignment if (value) {[OBJC setvalue:value forkey: Key];   }*/@implementationNSObject (Model)//Ivar: The member variable starts with an underscore//Property: Properties+ (Instancetype) modelwithdict: (Nsdictionary *) dict{IDOBJC =[[Self alloc] init]; //Runtime: According to the properties in the model, go to the dictionary to remove the corresponding value to the Model property assignment//1. Get all member variables in the model key//gets the member variable of which class//Count: Number of member variablesUnsignedintCount =0; //get array of member variablesIvar *ivarlist = Class_copyivarlist (self, &count); //Traverse all member variables     for(inti =0; I < count; i++) {        //Get member VariableIvar Ivar =Ivarlist[i]; //get member variable nameNSString *ivarname =[NSString Stringwithutf8string:ivar_getname (Ivar)]; //get member Variable typeNSString *ivartype =[NSString stringwithutf8string:ivar_gettypeencoding (Ivar)]; //@\ "User\"-UserIvartype = [Ivartype stringbyreplacingoccurrencesofstring:@"\ "" withstring:@ ""]; Ivartype = [Ivartype stringbyreplacingoccurrencesofstring:@"@"withstring:@ ""];                Get key NSString *key = [Ivarname substringfromindex:1];                Go to the dictionary to find the corresponding Value//Key:user value:nsdictionary id value = Dict[key]; Secondary conversions: Determine if value is a dictionary, and if so, the model of the Dictionary conversion layer//and the custom object needs to be converted if ([Value Iskindofclass:[nsdictionary class]] &&A MP;! [Ivartype hasprefix:@"Ns"]) {            //dictionary conversion to model USERDICT = user Model//which model to convert into//Get classClass Modelclass =nsclassfromstring (Ivartype); Value=[Modelclass Modelwithdict:value]; }                //assigning values to properties in a model        if(value) {[OBJC setvalue:value forkey:key]; }    }            returnOBJC;}voidTestint*count) {    *count =3;}@end

iOS Development Runtime Learning Five: KVC and KVO, using runtime to implement dictionary-to-model

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.