1. 程式人生 > >Runtime執行時用法1------獲取類屬性列表

Runtime執行時用法1------獲取類屬性列表

提起Runtime執行時很多初學者會望而卻步, 但是仔細想想, 我們要讀懂別人框架的實現原理, 這些東西還是需要去學習了,  正所謂, 怕什麼什麼就是你的缺點, 面對我們知識層面的不足, 我們一定要勇敢地去克服. 好了扯淡部分結束, 進入正題!

如標題所示, 本文將詳細說明如何獲取屬性列表, 以及用途!

對於任何想要使用的東西, 第一件事就是匯入標頭檔案, Runtime也不例外.  我們通過Runtime的方法可以獲取到物件的屬性列表, 然後就可以通過kvc的方式動態的給類的屬性賦值.  這種方法多用於字典轉模型中!下面就是字典轉模型的程式碼,  將此分類標頭檔案匯入到你的pch檔案中, 你的所有繼承自NSObject物件都有了,擴充套件類的方法!那麼你在模型檔案中就不用再寫字典轉模型的程式碼.  請閱讀以下程式碼

標頭檔案

//
//  NSObject+JLExterntion.h
//  NetNews
//
//  Created by Wangjunling on 16/5/26.
//  Copyright © 2016年 Wangjunling. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface NSObject (JLExterntion)
+ (instancetype)jl_objWithDic:(NSDictionary *)dic;
@end

實現檔案

//
//  NSObject+JLExterntion.m
//  NetNews
//
//  Created by Wangjunling on 16/5/26.
//  Copyright © 2016年 Wangjunling. All rights reserved.
//

#import "NSObject+JLExterntion.h"
#import <objc/runtime.h>

@implementation NSObject (JLExterntion)

+ (instancetype)jl_objWithDic:(NSDictionary *)dic {
    id object = [[self alloc] init];
    
    //獲取屬性列表
    NSArray *propertyList = [self jl_getProperties];
    
    //此方法會引起崩潰崩潰原因不清楚
//    [propertyList enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
//        [object setValue:dic[obj] forKey:obj];
//    }];
    
    [dic enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        
       
        // 判斷 key 是否在 proList 中
        if ([propertyList containsObject:key]) {
            //  說明屬性存在,可以使用 `KVC` 設定數值
            [object setValue:obj forKey:key];
        }
    }];
    
    return object;
}

+ (NSArray *)jl_getProperties {
    //用於存入屬性數量
    unsigned int outCount = 0;
    //獲取屬性陣列
    objc_property_t *propertyList = class_copyPropertyList([self class], &outCount);
    
    NSMutableArray *arrM = [NSMutableArray arrayWithCapacity:outCount];
    //遍歷陣列
    for (int i = 0; i < outCount; ++i) {
        objc_property_t property = propertyList[i];
       //獲取屬性名
        const char *cName = property_getName(property);
        //將其轉換成c字串
        NSString *propertyName = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding];
//        加入陣列
        [arrM addObject:propertyName];
    }
    //在使用了c函式的creat, copy等函式是記得手動釋放,要不然會引起記憶體洩露問題
    free(propertyList);
    return arrM.copy;
   
}


@end