博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
修复看不懂的 Console Log
阅读量:5894 次
发布时间:2019-06-19

本文共 9196 字,大约阅读时间需要 30 分钟。

大家好~ 我是大萌鱼。今天我跟大家分享的题目是:修复看不懂的
Console log

开发中,我们会经常碰到需要打印一个值,或者在我们的网络层中使用 Log 组件来打印我们的 RequestBody 或者 ResponseBody。但是对于一些容器类中的中文 NSLog 会以人类看不懂的形式 --- Unicode 来展示,但是在 Xcode 的控制台使用 LLVM 的 po 命令就会显示正确的中文,这是为什么呢?且听我为你娓娓道来~

在很多面向对象语言中,对象通常都会有一个 toString() 或者近似的方法。在 Objective-C 中也不例外,不过呢在 Objective-C 中这个方法叫做:

- (NSString *)description;复制代码

也有个姊妹函数:

- (NSString *)debugDescription;复制代码

这两个方法对于继承自 NSObject 的类都可以使用,通常情况下这两个方法没有区别,description 方法会在我们调用 NSLog 时会调用,debugDescription 只有在我们进行断点调试的时候才会调用。

在 的 Issue 9 Working with Strings 中提到 %@ 优先会调用 -descriptionWithLocale:level: ,查阅官方文档后发现 NSArray NSSet NSDictionary 中都有这个方法。

那么,接下我们就该考虑怎么做的问题了。我们需要分别继承 NSArrayNSSetNSDictionary 来重写改造这个方法吗?No No No 万万使不得,这在 Objc 语言中可不是最佳实践,究其原因,我会在后续写一篇文章来阐述为什么不应该,以及如果需要我们应该怎么做的文章,嘻嘻,留点悬念吧~

那么我们应该怎么办呢?究竟怎样才是最佳实践呢?Category wtf?! 不是说不能在 Category 重写主类方法吗? 当然不是咯,我们要知其然更要知其所以然,Category 中重写主类方法其实不是对主类方法进行了覆盖,而是“插队”,runtime 在运作的时候会优先调用排在方法列表前边的方法,而 Category 中的方法列表会排在前边。

接下来我们可以新建一个 FoundationContainer + Log.m 文件,重写 descriptionWithLocale:level: 方法,遍历我们的容器类就好了,示例代码我写在下边了,加了一些制表符使得输出更美观, Localelevel 参数含义我不过多介绍了,可以参考官方文档,No Code No BB,下面?开始上代码:

⚠️:由于源码内容过长,我们也准备了相应的 Demo,需要的朋友们可以关注微信公众号 “iOS 开发技术栈” 回复关键字 Console Log 获取噢~

扫码关注公众号后,回复关键字 Console Log 获取 Demo

#ifdef DEBUG@implementation NSSet(Log)- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level {    NSMutableString *desc = [NSMutableString string];        NSMutableString *originalStr = [[NSMutableString alloc] initWithCapacity:level];    for (NSUInteger i = 0; i < level; ++i) {        [originalStr appendString:@"\t"];    }    NSString *tab = @"\t";    if (level > 0) {        tab = originalStr;    }    [desc appendString:@"\t{(\n"];    [self enumerateObjectsUsingBlock:^(id  _Nonnull obj, BOOL * _Nonnull stop) {        if ([obj isKindOfClass:[NSDictionary class]]            || [obj isKindOfClass:[NSArray class]]            || [obj isKindOfClass:[NSSet class]]) {            NSString *str = [((NSDictionary *)obj) descriptionWithLocale:locale indent:level + 1];            [desc appendFormat:@"%@\t%@,\n", tab, str];        } else if ([obj isKindOfClass:[NSString class]]) {            [desc appendFormat:@"%@\t\"%@\",\n", tab, obj];        } else if ([obj isKindOfClass:[NSData class]]) {            // if is NSData,try parse            NSError *error = nil;            NSObject *result =  [NSJSONSerialization JSONObjectWithData:obj                                                                options:NSJSONReadingMutableContainers                                                                  error:&error];            if (error == nil && result != nil) {                if ([result isKindOfClass:[NSDictionary class]]                    || [result isKindOfClass:[NSArray class]]                    || [result isKindOfClass:[NSSet class]]) {                    NSString *str = [((NSDictionary *)result) descriptionWithLocale:locale indent:level + 1];                    [desc appendFormat:@"%@\t%@,\n", tab, str];                } else if ([obj isKindOfClass:[NSString class]]) {                    [desc appendFormat:@"%@\t\"%@\",\n", tab, result];                }            } else {                @try {                    NSString *str = [[NSString alloc] initWithData:obj encoding:NSUTF8StringEncoding];                    if (str != nil) {                        [desc appendFormat:@"%@\t\"%@\",\n", tab, str];                    } else {                        [desc appendFormat:@"%@\t%@,\n", tab, obj];                    }                }                @catch (NSException *exception) {                    [desc appendFormat:@"%@\t%@,\n", tab, obj];                }            }        } else {            [desc appendFormat:@"%@\t%@,\n", tab, obj];        }    }];    [desc appendFormat:@"%@)}", tab];    return desc;}@end@implementation NSArray (Log)- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level {    NSMutableString *desc = [NSMutableString string];        NSMutableString *originalStr = [[NSMutableString alloc] initWithCapacity:level];    for (NSUInteger i = 0; i < level; ++i) {        [originalStr appendString:@"\t"];    }    NSString *tab = @"";    if (level > 0) {        tab = originalStr;    }    [desc appendString:@"\t(\n"];    [self enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {        if ([obj isKindOfClass:[NSDictionary class]]            || [obj isKindOfClass:[NSArray class]]            || [obj isKindOfClass:[NSSet class]]) {            NSString *str = [((NSDictionary *)obj) descriptionWithLocale:locale indent:level + 1];            [desc appendFormat:@"%@\t%@,\n", tab, str];        } else if ([obj isKindOfClass:[NSString class]]) {            [desc appendFormat:@"%@\t\"%@\",\n", tab, obj];        } else if ([obj isKindOfClass:[NSData class]]) {                        NSError *error = nil;            NSObject *result =  [NSJSONSerialization JSONObjectWithData:obj                                                                options:NSJSONReadingMutableContainers                                                                  error:&error];            if (error == nil && result != nil) {                if ([result isKindOfClass:[NSDictionary class]]                    || [result isKindOfClass:[NSArray class]]                    || [result isKindOfClass:[NSSet class]]) {                    NSString *str = [((NSDictionary *)result) descriptionWithLocale:locale indent:level + 1];                    [desc appendFormat:@"%@\t%@,\n", tab, str];                } else if ([obj isKindOfClass:[NSString class]]) {                    [desc appendFormat:@"%@\t\"%@\",\n", tab, result];                }            } else {                @try {                    NSString *str = [[NSString alloc] initWithData:obj encoding:NSUTF8StringEncoding];                    if (str != nil) {                        [desc appendFormat:@"%@\t\"%@\",\n", tab, str];                    } else {                        [desc appendFormat:@"%@\t%@,\n", tab, obj];                    }                }                @catch (NSException *exception) {                    [desc appendFormat:@"%@\t%@,\n", tab, obj];                }            }        } else {            [desc appendFormat:@"%@\t%@,\n", tab, obj];        }    }];    [desc appendFormat:@"%@)", tab];        return desc;}@end@implementation NSDictionary (Log)- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level {    NSMutableString *desc = [NSMutableString string];        NSMutableString *originalStr = [[NSMutableString alloc] initWithCapacity:level];    for (NSUInteger i = 0; i < level; ++i) {        [originalStr appendString:@"\t"];    }        NSString *tab = @"";    if (level > 0) {        tab = originalStr;    }        [desc appendString:@"\t{\n"];        [self.allKeys enumerateObjectsUsingBlock:^(id  _Nonnull key, NSUInteger idx, BOOL * _Nonnull stop) {        id obj = [self objectForKey:key];                if ([obj isKindOfClass:[NSString class]]) {            [desc appendFormat:@"%@\t%@ = \"%@\",\n", tab, key, obj];        } else if ([obj isKindOfClass:[NSArray class]]                   || [obj isKindOfClass:[NSDictionary class]]                   || [obj isKindOfClass:[NSSet class]]) {            [desc appendFormat:@"%@\t%@ = %@,\n", tab, key, [obj descriptionWithLocale:locale indent:level + 1]];        } else if ([obj isKindOfClass:[NSData class]]) {                        NSError *error = nil;            NSObject *result =  [NSJSONSerialization JSONObjectWithData:obj                                                                options:NSJSONReadingMutableContainers                                                                  error:&error];            if (error == nil && result != nil) {                if ([result isKindOfClass:[NSDictionary class]]                    || [result isKindOfClass:[NSArray class]]                    || [result isKindOfClass:[NSSet class]]) {                    NSString *str = [((NSDictionary *)result) descriptionWithLocale:locale indent:level + 1];                    [desc appendFormat:@"%@\t%@ = %@,\n", tab, key, str];                } else if ([obj isKindOfClass:[NSString class]]) {                    [desc appendFormat:@"%@\t%@ = \"%@\",\n", tab, key, result];                }            } else {                @try {                    NSString *str = [[NSString alloc] initWithData:obj encoding:NSUTF8StringEncoding];                    if (str != nil) {                        [desc appendFormat:@"%@\t%@ = \"%@\",\n", tab, key, str];                    } else {                        [desc appendFormat:@"%@\t%@ = %@,\n", tab, key, obj];                    }                }                @catch (NSException *exception) {                    [desc appendFormat:@"%@\t%@ = %@,\n", tab, key, obj];                }            }        } else {            [desc appendFormat:@"%@\t%@ = %@,\n", tab, key, obj];        }    }];    [desc appendFormat:@"%@}", tab];        return desc;}@end#endif复制代码

经过测试一切完美 ؏؏☝ᖗ乛◡乛ᖘ☝؏؏ ,感谢大家收看,记得点击关注哦~

[ 热文推荐 ]
  • 不知己高的 UITableHeaderView

  • 忘不了的 TODOS & FIXMES & ERRORS

  • iOS指定初始化方法的正确使用姿势

  • WWDC 2018 更新了什么?

关注 "iOS开发技术栈" ,看奇技淫巧

转载地址:http://kpisx.baihongyu.com/

你可能感兴趣的文章
Mac OSX 中java7 java8环境的配置
查看>>
30分钟入门Java
查看>>
elasticsearch学习——环境搭建2
查看>>
数据科学求职过程中总结的四点经验
查看>>
git代码首次提交
查看>>
mysql安装,远程连接,以及修改密码
查看>>
Dart服务器端 shelf_route包
查看>>
spring security(四)
查看>>
Mybatis查询返回Map类型数据
查看>>
java的深拷贝与浅拷贝
查看>>
程序员如何提高工作效率
查看>>
数据库水平切分(其他应用)
查看>>
easyui 将已经是 textbox 的输入框改成时间框
查看>>
python基础学习整理——字典
查看>>
promise
查看>>
如何使用ABSL代码调用Web service
查看>>
将Java应用部署到SAP云平台neo环境的两种方式
查看>>
SAP CRM和C4C的客户主数据修改历史记录查询
查看>>
如何在CRM WebClient UI里使用HANA Live Report
查看>>
树莓派终端安装FTP服务器
查看>>