美文网首页
OBJDescription 格式化输出 解决字典数组自定义类的

OBJDescription 格式化输出 解决字典数组自定义类的

作者: AliceJordan | 来源:发表于2019-01-19 19:04 被阅读0次

格式化输出

最近在看52个方法这本书,其中有一个方法讲的就是关于编写Description方法的,这个方法我之前也有看过是关于打印对象信息的方法,这次看的时候突发奇想想去做一个Pod库 省的以后再去找方法改写,于是乎周末在家就写了一个OBJDescription,希望各位大大们多多提意见。

关于输出

这里就引用书上的一些描述,调试程序时,经常需要打印并且查看对象信息,一种方法是编写对象的全部属性都输出到日志中,像我们平时使用的NSLog一个变量,在调用NSLog的时候,对象会收到description消息,该方法所返回的描述信息将取代格式字符串里面的%@ 官方文档的解释 其实说白了就是要打印的内容。

痛点

在我们打印NSArray,NSDictionary对象的时候都可以显示出Array的元素内容的
比如:

NSArray *array = @[@"A",@"B"];
NSLog(@"%@",array);

输出:
array = (
    "A",
    "B"
)

字典的输出也是类似的比较可以看出字典的内容,但是如我们自定义一个类,然后输出来看看就是类似于<类名: 对象的内存地址>

这里图床挂了 这两天整下上传图片

<Person:0X7facfabe1270>

这样对于Debug的观察极其的舒服,我们看不到有用的信息啊。

解决方法

这个方法定义在NSObjc协议里,不过NSObject类也实现了他,因为NSObject并不是唯一一个跟类,所以许多方法都要定义在NSObjct协议里面,比方说,NSProxy也是一个遵循了NSObject协议的根类,由于description定义在协议里面,因此NSProxy和他的子类也是需要实现这个方法的,前面是书上说的,我并没抓到他们的因果关系,但是重要的一点是他所说的NSObject实现了这个方法,我的想法是通过NSObject的分类在分类中通过runtime获取到类的成员变量然后将他们组成成一个NSDictionary通过NSDictionary的description打印出来 这里的代码不是很复杂,就是利用runtime获取成员变量然后对于字符串的一些操作组成字典,返回给重写的description方法。

// 重写description 方法
- (NSString *)description
{
    NSDictionary *dic = [self sharker_ivars];
    return [dic description];
}

// 获取成员变量
- (NSDictionary *)sharker_ivars{
    NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];
    unsigned int outCount = 0;
    Ivar * ivars = class_copyIvarList([self class], &outCount);
    for (unsigned int i = 0; i < outCount; i ++) {
        Ivar ivar = ivars[i];
        const char * name = ivar_getName(ivar);
        const char * type = ivar_getTypeEncoding(ivar);
        NSString *nameStr = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
        NSString *typeStr = [NSString stringWithCString:type encoding:NSUTF8StringEncoding];
        nameStr = [nameStr stringByReplacingOccurrencesOfString:@"_" withString:@""];
        typeStr = [typeStr stringByReplacingOccurrencesOfString:@"\"" withString:@""];
        typeStr = [typeStr stringByReplacingOccurrencesOfString:@"\\" withString:@""];
        typeStr = [typeStr stringByReplacingOccurrencesOfString:@"@" withString:@""];
        [dic setObject:[self valueForKey:nameStr] forKey:[NSString stringWithFormat:@"%@",nameStr]];
    }
    free(ivars);
    return [dic copy];
}

这里有遇到了一个问题就是关于字典中含有中午输出会出现乱码的情况,网上有很多这样的例子,我根据其中一个做了写修改,这里放出关于NSDictionary的关键代码

/**
 格式化输出字典

 @param level 层级
 @return 格式化字符串
 */
- (NSString *)sharker_descriptionWithLevel:(int)level{
    NSString *subSpace = [self sharker_getSpaceWithLevel:level];
    NSString *space = [self sharker_getSpaceWithLevel:level-1];
    NSMutableString *retString = [[NSMutableString alloc] init];
    //    添加 {
    [retString appendString:@"{"];
    [self enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        if ([obj isKindOfClass:[NSString class]]) {
            NSString *value = (NSString *)obj;
            value = [value stringByReplacingOccurrencesOfString:@"\0" withString:@"\\0"];
            NSString *subString = [NSString stringWithFormat:@"\n%@\"%@\" : \"%@\",",subSpace,key,value];
            [retString appendString:subString];
        }else if ([obj isKindOfClass:[NSDictionary class]]){
            NSDictionary *dic = (NSDictionary *)obj;
            NSString *str = [dic sharker_descriptionWithLevel:level+1];
            str = [NSString stringWithFormat:@"\n%@\"%@\" : %@,", subSpace, key, str];
            [retString appendString:str];
        }else if ([obj isKindOfClass:[NSArray class]]){
            NSArray *arr = (NSArray *)obj;
            NSString *str = [arr descriptionWithLocale:nil indent:level+1];
            str = [NSString stringWithFormat:@"\n%@\"%@\" : %@,", subSpace, key, str];
            [retString appendString:str];
        }else{
//            字典的属性是其他类型 可以空充需要的打印方式
            NSString *str = [NSString stringWithFormat:@"\n%@\"%@\" : %@,", subSpace, key, obj];
            [retString appendString:str];
        }
    }];
    if ([retString hasPrefix:@","]) {
        [retString deleteCharactersInRange:NSMakeRange(retString.length-1, 1)];
    }
    //    添加 }
    [retString appendString:[NSString stringWithFormat:@"\n%@}",space]];
    return retString;
}

思路还是很简单的就是通过判断类型,然后格式化输出,乱码的解决就是转化为字符串输出就好了,里面还包含了像是字典嵌套的的情况,通过获取层级,添加空格使得输出的效果更好。

相关话题

  • debugDescription

    这里关于打印还有几个方法,其中想debugDescription就是我们平时在使用lldb调试po调用的,但是如果没有特殊实现的话他其实最后就是调用的description方法,如果我们觉得信息不够全面可以在debugDescription方法里面添加,这个方法只会在控制台,用lldb时输出。

  • descriptionWithLocale:indent

    ==*注:优先级 - (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level > - (NSString *)description 这个方法是被NSArray 与 NSDictionary 实现的方法
    官方描述
    总的说就是为了输出的格式化与美观性.

关于

最后放出demon的地址GitHub

作者 Sharker
邮箱 aaksharker@gmail.com
QQ 1548742234

参考阅读 谢谢各位的分享
参考
参考
参考

相关文章

  • OBJDescription 格式化输出 解决字典数组自定义类的

    格式化输出 最近在看52个方法这本书,其中有一个方法讲的就是关于编写Description方法的,这个方法我之前也...

  • iOS 开发记录

    打印方法名 类、方法判断 emoji表情转换 数组和字典与NSData互转 字典、JSON互转 自定义结构体(类似...

  • iOS 数组和字典NSLog及po输出中文

    前言 当你搜索“iOS 数组和字典NSLog输出中文” 时会找到:这个 iOS开发——输出中文(字典和数组)这个 ...

  • Python3 print函数用法总结

    1、字符串和数值类型可以直接输出 2.变量 各种数据类型数值、布尔、列表和字典等都可以直接输出 3.格式化输出 类...

  • 2018-06-09 NSDictionary

    字典Dictionary是集合类的一种。集合:数组array、字典dictionary、set;数组是有顺序的,且...

  • Jackson 格式化输出

    1. 未格式化的打印 (1)需要序列化的类 (2)序列化工具类 (3)测试类 控制台输出: 2. 格式化输出 运行...

  • swift 基本认识

    1,格式化创建字符串 2,数组 array(跟 OC 里面的数组是可以互相转换的) 3,字典 dictionary...

  • Python 序列化操作

    1. json 操作写字典到文件 从文件中读出字典 当然我们也可以把字典直接转成字符串 再转成字典类型 格式化输出...

  • iOS归档看这篇就够了

    归档的作用 之前将数据存储到本地,只能是字符串、数组、字典、NSNuber、BOOL等容器类对象,不能将自定义对象...

  • iOS解决数组和字典输出汉字问题

    解决前: 解决后: 注意:看第一张图片,我取出数组里的元素和字典里的值的时候,是可以正常输出汉字的.所以解决方案来...

网友评论

      本文标题:OBJDescription 格式化输出 解决字典数组自定义类的

      本文链接:https://www.haomeiwen.com/subject/ccbzdqtx.html