iOS開發(fā)之遍歷Model類的屬性并完善使用Runtime給Model類賦值
一、獲取Model的實體屬性
1.要想遍歷Model類的屬性,首先得通過Runtime來獲取該Model類有哪些屬性,輸出Model的所有屬性的值可不像遍歷Dictionary和Array那樣一個for循環(huán)搞定的,下面的方法是通過Runtime來獲取Model類的屬性字符串,并以數(shù)組的形式返回。代碼如下:
- ///通過運行時獲取當(dāng)前對象的所有屬性的名稱,以數(shù)組的形式返回
- - (NSArray *) allPropertyNames{
- ///存儲所有的屬性名稱
- NSMutableArray *allNames = [[NSMutableArray alloc] init];
- ///存儲屬性的個數(shù)
- unsigned int propertyCount = 0;
- ///通過運行時獲取當(dāng)前類的屬性
- objc_property_t *propertys = class_copyPropertyList([self class], &propertyCount);
- //把屬性放到數(shù)組中
- 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.獲取到Model類的屬性方法后需要把屬性字符串生成get方法,我們可以執(zhí)行g(shù)et方法來獲取Model屬性的值,下方的方法是根據(jù)屬性字符串來獲取屬性的getter方法,OC中屬性的getter方法的名字和屬性的名字是一致的,生成getter方法比較簡單,具體代碼如下:
- #pragma mark -- 通過字符串來創(chuàng)建該字符串的Setter方法,并返回
- - (SEL) creatGetterWithPropertyName: (NSString *) propertyName{
- //1.返回get方法: oc中的get方法就是屬性的本身
- return NSSelectorFromString(propertyName);
- }
二、Get方法的執(zhí)行
接下來要做的是通過Runtime來執(zhí)行Getter方法,這一塊需要通過方法的簽名來執(zhí)行Getter方法。在OC的運行時中要執(zhí)行的方法需要傳入?yún)?shù)或者需要接收返回值時,需要通過方法的簽名來調(diào)用方法。下面的代碼就是創(chuàng)建方法的簽名,然后通過簽名來獲取調(diào)用的對象,在下邊的方中回調(diào)用上述兩個方法在通過方法的簽名來獲取Model屬性的值,具體代碼如下:
- - (void) displayCurrentModleProperty{
- //獲取實體類的屬性名
- NSArray *array = [self allPropertyNames];
- //拼接參數(shù)
- 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];
- //從簽名獲得調(diào)用對象
- NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
- //設(shè)置target
- [invocation setTarget:self];
- //設(shè)置selector
- [invocation setSelector:getSel];
- //接收返回的值
- NSObject *__unsafe_unretained returnValue = nil;
- //調(diào)用
- [invocation invoke];
- //接收返回值
- [invocation getReturnValue:&returnValue];
- [resultString appendFormat:@"%@\n", returnValue];
- }
- }
- NSLog(@"%@", resultString);
- }
執(zhí)行上述方法就可以輸入Model中的屬性的值,下面就在main函數(shù)中對Model賦完值后調(diào)用上述方法輸出一下Model的屬性值,調(diào)用代碼如下所示:
- BeautifulGirlModel *beautifulGirl = [BeautifulGirlModel modelWithDictionary:data];
- [beautifulGirl displayCurrentModleProperty];
運行結(jié)果如下,下面的輸出結(jié)果是Model中屬性的值。
三、Dictionary的Key與Model的屬性不同的處理方式
有時候會遇到字典的key和Model的屬性不一樣的情況,那么如何去解決這個問題呢?最簡單的做法是在具體的實體類中去維護一個映射關(guān)系方法,通過這個方法我們可以獲取相應(yīng)的的映射關(guān)系。
- #pragma 返回屬性和字典key的映射關(guān)系
- -(NSDictionary *) propertyMapDic{
- return nil;
- }
2.修改一下我們的便利初始化方法,在有映射字典的情況和沒有映射字典的情況下調(diào)用的方法是不一樣的,便利初始化方法的代碼如下:
- - (instancetype)initWithDictionary: (NSDictionary *) data{
- {
- self = [super init];
- if (self) {
- if ([self propertyMapDic] == nil) {
- [self assginToPropertyWithDictionary:data];
- } else {
- [self assginToPropertyWithNoMapDictionary:data];
- }
- }
- return self;
- }
- }
3.接下來就將實現(xiàn)有映射關(guān)系要調(diào)用的方法,這個方法就是通過映射關(guān)系把字典的key轉(zhuǎn)換成與property的名字一樣的字典,然后調(diào)用之前的賦值方法,具體代碼如下:
- #pragma 根據(jù)映射關(guān)系來給Model的屬性賦值
- -(void) assginToPropertyWithNoMapDictionary: (NSDictionary *) data{
- ///獲取字典和Model屬性的映射關(guān)系
- NSDictionary *propertyMapDic = [self propertyMapDic];
- ///轉(zhuǎn)化成key和property一樣的字典,然后調(diào)用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.創(chuàng)建一個BadBoyModel, 并重寫propertyMapDic方法,并且在propertyMapDic方法中給出映射關(guān)系并返回該映射關(guān)系對應(yīng)的字典。
(1)BadBoyModel的屬性如下:
- //
- // 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)重寫映射方法,映射字典的key是要轉(zhuǎn)換字典的key, Value是對應(yīng)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的映射關(guān)系
- -(NSDictionary *) propertyMapDic{
- return @{@"keyBoy1":@"boy1",
- @"keyBoy2":@"boy2",
- @"keyBoy3":@"boy3",
- @"keyBoy4":@"boy4",};
- }
- @end
5.在main函數(shù)中進行測試
(1)生成我們的數(shù)值字典,字典的key與要賦值Model的屬性不同,下面的循環(huán)就是要生成測試使用的數(shù)據(jù):
- //生成Dic的Key與Model的屬性不一樣的字典。
- NSMutableDictionary *data1 = [[NSMutableDictionary alloc] init];
- //創(chuàng)建測試適用的字典
- 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) 實例化Model并輸出結(jié)果,當(dāng)然之前的代碼也是可以使用的。
- BadBoyModel *badBoyModel = [BadBoyModel modelWithDictionary:data1];
- [badBoyModel displayCurrentModleProperty];
運行輸出結(jié)果如下:
今天博客就到這,至此,Model的基類最基本的方法封裝的也就差不多了,根據(jù)具體需求可以在添加新的方法
作者:青玉伏案
出處:http://www.cnblogs.com/ludashi/