代码改变世界

iOS 高效开发-----实现description 方法 (续)

2015-05-20 10:55  PingKang  阅读(516)  评论(0编辑  收藏  举报

在 “iOS 高效开发-----实现description 方法”这篇文章的最后,我留下了一个问题,就是,如果要给每个自定义的类覆写description方法和debugDescription方法 ,那将是一件非常庞大的工作量 ,因为自定义的类很多 ,而且每个自定义的类中的属性都会随着需求的修改出现变化 ,那么就又得修改这两个方法,那就变得无穷无尽了,永无宁日了,要么不用,要么就要找到更好得方法去用。

接下来,我们会用到动态运行时runtime。

我们先假设我们要处理的类中的属性都是OC的对象,实现的思路如下:

思路一:可以定义一个父类,在父类中实现description方法和debugDescription方法,然后令每一个类都成为其子类,具体实现如下:

//
//  PingkFather.h
//  LearnEffective2.0
//
//  Created by pk on 15/5/20.
//  Copyright (c) 2015年 iss. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface PingkFather : NSObject

@end

  

//
//  PingkFather.m
//  LearnEffective2.0
//
//  Created by pk on 15/5/20.
//  Copyright (c) 2015年 iss. All rights reserved.
//

#import "PingkFather.h"
#import <objc/runtime.h>

@implementation PingkFather


- (NSDictionary *) descriptionMehtod:(id)obj{
    
    NSMutableDictionary * dic = [NSMutableDictionary dictionary];
    
    u_int count;
    //获取所有的属性
    objc_property_t *properties = class_copyPropertyList([obj class], &count);
    for (int i = 0; i<count; i++) {
        //得到属性的名称
        const char * propertyName = property_getName(properties[i]);
        id objValue;
        //将属性转化位字符串
        NSString * key = [NSString stringWithUTF8String:propertyName];
        //取值
        objValue = [obj valueForKey:key];
        //写入字典中
        [dic setObject:objValue forKey:key];
    }
    
    NSDictionary * dictionary = [dic copy];
    return dictionary;
}


-(NSString *)description
{
    return [NSString stringWithFormat:@"%@",[self descriptionMehtod:self]];
}

-(NSString *)debugDescription
{
    return [NSString stringWithFormat:@"<%@: %p,%@>",
            [self class],
            self,
            [self descriptionMehtod:self]];
}


@end

  

然后定义一个继承自PingkFather的子类,代码如下:

//
//  PingkSon.h
//  LearnEffective2.0
//
//  Created by pk on 15/5/20.
//  Copyright (c) 2015年 iss. All rights reserved.
//

#import "PingkFather.h"

@interface PingkSon : PingkFather

@property (nonatomic,copy,readonly)NSString * selfName;
@property (nonatomic,copy,readonly)NSString * fatherName;
@property (nonatomic,copy,readonly)NSString * motherName;

- (id)initWithSelfName:(NSString *)selfName andFatherName:(NSString *)fatherName andMotherName:(NSString *)motherName;


@end

  

//
//  PingkSon.m
//  LearnEffective2.0
//
//  Created by pk on 15/5/20.
//  Copyright (c) 2015年 iss. All rights reserved.
//

#import "PingkSon.h"

@implementation PingkSon


- (id)initWithSelfName:(NSString *)selfName andFatherName:(NSString *)fatherName andMotherName:(NSString *)motherName {
	
    if (self = [super init]) {
        _selfName   = selfName;
        _fatherName = fatherName;
        _motherName = motherName;
    }
    return self;
}
@end

  

测试:

这种实现方法是最好的,也是最简单的,子类不用再实现任何代码。

另外一种思路,使用内敛函数,实现如下:

NS_INLINE NSDictionary * descriptionMehtod(id obj){
    
    NSMutableDictionary * dic = [NSMutableDictionary dictionary];

    u_int count;
    //获取所有的属性
    objc_property_t *properties = class_copyPropertyList([obj class], &count);
    for (int i = 0; i<count; i++) {
        //得到属性的名称
        const char * propertyName = property_getName(properties[i]);
        id objValue;
        //将属性转化位字符串
        NSString * key = [NSString stringWithUTF8String:propertyName];
        //取值
        objValue = [obj valueForKey:key];
        //写入字典中
        [dic setObject:objValue forKey:key];
    }
    
    NSDictionary * dictionary = [dic copy];
    return dictionary;
}

但是这种方法的话,不仅每个类要引入包含这个函数的头文件,而且每个类还要自己实现description方法和debugDescription方法;

相比较而言,还是用类继承的方法实现比较简单,而且一旦出错,改动也极少,只要修改继承的类名就可以。

从这两种实现思路可以看出,代码越少,维护越好!