oc 运行时方法(二)

在开发中,我们经常通过打印输出某一个模型对象的某一个属性值。 比如有一个 CZPerson 对象,CZPerson 有name,age,weight等属性。如果想打印输出每一个属性对应的值,一般有两种方法:

1、拼接字符串。比如 NSLog(@"name = %@,age = %d weight = %f",name,age,weight);

2、重新模型对象的 description 方法,在方法中返回要输出的字符串(本质还是要拼接字符串)。然后就可以直接使用 NSLog(@"%@",person);来查看对象的各属性值。

以上两种方法都能实现查看模型各个属性值的要求。但拼接字符串这个操作很浪费时间,而且没有技术含量。如果整个项目中有很多模型都要这样拼接输出查看属性值。那么这将会是很蛋疼的事情。

为了解决上面的问题,我利用运行时机制来对系统的输出作了小小的改造。为 NSObject 添加了一个分类,分类代码如下

//分类头文件
#import <Foundation/Foundation.h>
@interface NSObject (Log)

@end

// 分类.m 文件
#import <UIKit/UIKit.h>
#import "NSObject+Log.h"
#import <objc/runtime.h>
@implementation NSObject (Log)
+ (void)load {
    // 交换两个方法的实现
    method_exchangeImplementations(class_getInstanceMethod([NSObject class], @selector(description)), class_getInstanceMethod([NSObject class], @selector(pkxDescription)));
}
/**
 *  该方法是用来自定义模型(直接继承NSObject)的输出格式
 *
 *  @return 格式化后的字符串
 */
- (NSString *)pkxDescription{
    Class class = [self class];
    // 0.如果是UIResponder或CALayer的子类,就使用系统的默认输出格式
    if ( <span class="s1" style="font-family: Arial, Helvetica, sans-serif;">[[class </span><span class="s2" style="font-family: Arial, Helvetica, sans-serif;">description</span><span class="s1" style="font-family: Arial, Helvetica, sans-serif;">] </span><span class="s2" style="font-family: Arial, Helvetica, sans-serif;">hasPrefix</span><span class="s1" style="font-family: Arial, Helvetica, sans-serif;">:</span><span class="s3" style="font-family: Arial, Helvetica, sans-serif;">@"NS"</span><span class="s1" style="font-family: Arial, Helvetica, sans-serif;">] ||</span><span style="font-family: Arial, Helvetica, sans-serif;">[class isSubclassOfClass:[UIResponder class]] ||</span>
<span style="font-family: Arial, Helvetica, sans-serif;"><span style="white-space:pre">		</span> [class isSubclassOfClass:[CALayer class]])return [self pkxDescription];</span>
    NSMutableString *resultStr = [NSMutableString stringWithFormat:@"%@ = {\n",[self pkxDescription]];
    while (class != [NSObject class]) {
        unsigned int count = 0;
        // 1.获取类成员变量列表,count为类成员变量数量
        Ivar *vars = class_copyIvarList(class, &count);
        for (int index = 0; index < count; index ++) {
            // 2.根据索引获得指定位置的成员变量
            Ivar var = vars[index];
            // 3.获得成员变量名
            const char *name = ivar_getName(var);
            // 4.成员变量名转化成oc字符串
            NSString *varName = [NSString stringWithUTF8String:name];
            // 5.获得成员变量对应的值
            id value = [self valueForKey:varName];
            [resultStr appendFormat:@"\t%@ = %@;\n", varName, value];
        }
        // 6.释放指针
        free(vars);
        // 7.获得父类
        class = class_getSuperclass(class);
    }
    [resultStr appendString:@"}\n"];
    return resultStr;
}
@end

只要将上面分类添加到项目中,在打印输出模型对象的时候就可以直接使用 NSLog(@"%@",person);这样就能将 person 对象的所有属性名和对应的属性值打印出来,不需要在拼接字符串了。


发布了10 篇原创文章 · 获赞 1 · 访问量 5894

猜你喜欢

转载自blog.csdn.net/pkxwyf/article/details/41791545