iOS dev > Learning-traverse the properties of the model class and refine the assignment of the model class using runtime

Source: Internet
Author: User

In a previous day's blog, "iOS development uses runtime to assign values to the Model class," describes how to use the runtime to assign a value to an attribute in the base class of an entity class, as long as the dictionary key must be the same as the property name of the entity class. The setter method is then generated and executed by the runtime to assign values to the properties of the model class.

The benefits of assigning values to model class attributes through runtime are many, which facilitates later maintenance of the Code and improves development efficiency. When you get the parsed dictionary, you don't have to assign the value of the dictionary to the properties of the corresponding model class by key, and this blog will show you how to iterate through the values of the properties in the model, and give the dictionary key and the model's property name differently.

The next step is to add the property values of the model class through runtime in the model base class based on the previous blog code.

First, get the entity properties of model

1. To traverse the properties of the model class, you first have to go through the runtime to get the properties of the model class, and the value of all the properties of the output model is not like traversing a For loop with dictionary and array. The following method uses the runtime to obtain the property string for the model class and returns it as an array. The code is as follows:

///通过运行时获取当前对象的所有属性的名称,以数组的形式返回 - (NSArray *) allPropertyNames{ ///存储所有的属性名称 NSMutableArray *allNames = [[NSMutableArray alloc] init]; ///存储属性的个数 unsigned int propertyCount = 0; ///通过运行时获取当前类的属性 objc_property_t *propertys = class_copyPropertyList([self class], &propertyCount); //把属性放到数组中 for (int i = 0; i < propertyCount; i ++) { ///取出第一个属性 objc_property_t property = propertys[i]; const char * propertyName = property_getName(property); [allNames addObject:[NSString stringWithUTF8String:propertyName]]; } ///释放 free(propertys); return allNames; }

2. After obtaining the property method of the model class, you need to generate a Get method for the property string, we can execute the GET method to get the value of the Model property, and the method below is to get the getter method of the property based on the property string. The name of the getter method of the attribute in OC is the same as the name of the property, and the generated getter method is relatively simple, the code is as follows:

#pragma mark -- 通过字符串来创建该字符串的Setter方法,并返回 - (SEL) creatGetterWithPropertyName: (NSString *) propertyName{ //1.返回get方法: oc中的get方法就是属性的本身 return  NSSelectorFromString(propertyName); }

Second, the Get method execution

The next thing to do is to execute the Getter method through the runtime, which requires the method's signature to execute the Getter method. The method needs to be called through the signature of the method when the method to be executed in the OC runtime needs to pass in parameters or need to receive the return value. The following code is to create the signature of the method, and then through the signature to get the called object, in the bottom of the observes callback call the above two methods in passing the signature of the method to get the value of the Model property, the specific code is as follows:

- (void) displayCurrentModleProperty{ //获取实体类的属性名 NSArray *array = [self allPropertyNames]; //拼接参数 NSMutableString *resultString = [[NSMutableString alloc] init]; for (int i = 0; i < array.count; i ++) { //获取get方法 SEL getSel = [self creatGetterWithPropertyName:array[i]]; if ([self respondsToSelector:getSel]) { //获得类和方法的签名 NSMethodSignature *signature = [self methodSignatureForSelector:getSel]; //从签名获得调用对象 NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; //设置target [invocation setTarget:self]; //设置selector [invocation setSelector:getSel]; //接收返回的值 NSObject *__unsafe_unretained returnValue = nil; //调用 [invocation invoke]; //接收返回值 [invocation getReturnValue:&returnValue]; [resultString appendFormat:@ "%@\n" , returnValue]; } } NSLog(@ "%@" , resultString); }

Execute the above method to enter the value of the property in the model, and then call the above method to output the model's property value after the model is assigned a value in the main function, the calling code looks like this:

BeautifulGirlModel *beautifulGirl = [BeautifulGirlModel modelWithDictionary:data]; [beautifulGirl displayCurrentModleProperty];

The result of the operation is as follows, and the output below is the value of the property in model.

Third, the dictionary key and the model properties of different processing methods

Sometimes the dictionary key and model properties are different, so how to solve this problem? The simplest approach is to maintain a mapping relationship method in a specific entity class, in which we can obtain a corresponding mapping relationship.

#pragma 返回属性和字典key的映射关系 -(NSDictionary *) propertyMapDic{ return  nil; }

2. Modify our convenient initialization method, in the case of a mapped dictionary and without a mapped dictionary, the method is different, the code to facilitate the initialization method is as follows:

- (instancetype)initWithDictionary: (NSDictionary *) data{ { self = [ super init]; if (self) { if ([self propertyMapDic] == nil) { [self assginToPropertyWithDictionary:data]; else { [self assginToPropertyWithNoMapDictionary:data]; } } return self; } }

3. The next step is to implement a mapping relationship to invoke the method, this method is to convert the dictionary key into a dictionary with the name of the property by mapping the relationship, and then call the previous assignment method, the code is as follows:

#pragma 根据映射关系来给Model的属性赋值 -(void) assginToPropertyWithNoMapDictionary: (NSDictionary *) data{ ///获取字典和Model属性的映射关系 NSDictionary *propertyMapDic = [self propertyMapDic]; ///转化成key和property一样的字典,然后调用assginToPropertyWithDictionary方法 NSArray *dicKey = [data allKeys]; NSMutableDictionary *tempDic = [[NSMutableDictionary alloc] initWithCapacity:dicKey.count]; for (int i = 0; i < dicKey.count; i ++) { NSString *key = dicKey[i]; [tempDic setObject:data[key] forKey:propertyMapDic[key]]; } [self assginToPropertyWithDictionary:tempDic]; }

4. Create a Badboymodel and override the Propertymapdic method, and give the mapping relationship in the Propertymapdic method and return the dictionary corresponding to the mapping.

(1) The properties of the Badboymodel are as follows:

// // BadBoyModel.h // BaseModelProject // // Created by Mr.LuDashi on 15/7/24. // Copyright (c) 2015年 ludashi. All rights reserved. // #import "BaseModelObject.h" @interface BadBoyModel : BaseModelObject @property (nonatomic, copy) NSString *boy1; @property (nonatomic, copy) NSString *boy2; @property (nonatomic, copy) NSString *boy3; @property (nonatomic, copy) NSString *boy4; @end

(2) Rewrite the mapping method, the key of the mapping dictionary is the key to convert the dictionary, value is the property name of the corresponding model.

// // BadBoyModel.m // BaseModelProject // // Created by Mr.LuDashi on 15/7/24. // Copyright (c) 2015年 ludashi. All rights reserved. // #import "BadBoyModel.h" @implementation BadBoyModel #pragma 返回属性和字典key的映射关系 -(NSDictionary *) propertyMapDic{ return @{@ "keyBoy1" :@ "boy1" , @ "keyBoy2" :@ "boy2" , @ "keyBoy3" :@ "boy3" , @ "keyBoy4" :@ "boy4" ,}; } @end

5. Test in the main function

(1) Generate our numerical dictionary, the key of the dictionary is different from the property to be assigned the model, the following loop is to generate the data used by the test:

//生成Dic的Key与Model的属性不一样的字典。 NSMutableDictionary *data1 = [[NSMutableDictionary alloc] init]; //创建测试适用的字典 for (int i = 1; i <= 4; i ++){ NSString *key = [NSString stringWithFormat:@ "keyBoy%d" , i]; NSString *value = [NSString stringWithFormat:@ "我是第%d个坏男孩" , i]; [data1 setObject:value forKey:key]; }

(2) Instantiate the model and output the results, of course, the previous code is also available.

BadBoyModel *badBoyModel = [BadBoyModel modelWithDictionary:data1];  [badBoyModel displayCurrentModleProperty];

The results of the run output are as follows:

Today the blog is here, so far, the model base class the most basic method encapsulation is almost, according to the specific requirements can be added new methods

Green Jade Desk


This article is copyright to the author and the blog Park, Welcome to reprint, but without the consent of the author must retain this paragraph, and in the article page obvious location to the original link, otherwise reserves the right to pursue legal responsibility.

If there are any errors in the text, please note. Lest more people be misled.

iOS dev > Learning-traverse the properties of the model class and refine the assignment of the model class using runtime

Related Article

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

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: and provide relevant evidence. A staff member will contact you within 5 working days.