Xcode 控制台打印Unicode字符串转换为中文

因为有好几个童鞋问过这个事了,参考ZXPUnicode:
首先编码转换的代码可以是:

- (NSString *)stringByReplaceUnicode:(NSString *)unicodeString
{
    NSMutableString *convertedString = [unicodeString mutableCopy];
    [convertedString replaceOccurrencesOfString:@"\\U" withString:@"\\u" options:0 range:NSMakeRange(0, convertedString.length)];
    CFStringRef transform = CFSTR("Any-Hex/Java");
    CFStringTransform((__bridge CFMutableStringRef)convertedString, NULL, transform, YES);
    
    return convertedString;
}

虽然这样可以随便做category手动调用了,但还是需要引用头文件,不方便。所以需要做Method Swizzling,替换掉系统的description相关方法,在自定义交换方法中添加如上述代码类似的编码转换操作,一劳永逸(。◕ฺ∀◕ฺ)。具体可以是对NSDictionaryNSArray以及NSSet作一个category,在类被初始加载调用load方法时做Method Swizzling:

+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        zx_swizzleSelector([self class], @selector(descriptionWithLocale:indent:), @selector(zx_descriptionWithLocale:indent:));
    });
}
- (NSString *)zx_descriptionWithLocale:(id)locale indent:(NSUInteger)level
{
    return [self stringByReplaceUnicode:[self zx_descriptionWithLocale:locale indent:level]];
}

swizzleSelector中交换了两个方法的实现。所以方法中调用zx_descriptionWithLocale:indent:其实是调用的原生的descriptionWithLocale:indent:方法。在系统方法返回时,进行编码转换就OK啦(。◕ฺ∀◕ฺ)。
原生的descriptionWithLocale:indent:方法是这样获取描述的: 如果元素是NSString对象则直接返回它; 当元素响应descriptionWithLocale:indent:方法时,调用方法获得该元素的字符串描述; 当元素响应descriptionWithLocale:方法时,调用方法获得该元素的字符串描述; 如果上述条件都不符合,就会调用该元素的description方法获取字符串描述。

原生方法执行遍历子元素的时候,还是会调用descriptionWithLocale:indent:方法来获取子元素的描述,当原生方法被调用时,因方法实现的交换又会执行自定义的交换方法的代码,形成间接递归,上述条件符合时原生方法会返回正确描述开始回归,回归时依次进行编码转换。这样有个小小的问题,就是回归过程中已经被编码转换过的字符串有可能会被重复转换好多次。这里我们交换的是descriptionWithLocale:indent:这一个原生方法。如果可以的话,可以只交换原生的description方法,然后输出的时候调一下description(例如你有个字典dict,这样打印:NSLog(@"%@", dic.description)), 这么做只是将系统方法返回的最终描述进行了一次编码转换。ps: 如果你不嫌麻烦的话,可以这么用 ๑乛◡乛๑ 。。。。

补上Method Swizzling代码:

static inline void zx_swizzleSelector(Class theClass, SEL originalSelector, SEL swizzledSelector)
{
    Method originalMethod = class_getInstanceMethod(theClass, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(theClass, swizzledSelector);
    
    BOOL didAddMethod =
    class_addMethod(theClass,
                    originalSelector,
                    method_getImplementation(swizzledMethod),
                    method_getTypeEncoding(swizzledMethod));
    
    if (didAddMethod) {
        class_replaceMethod(theClass,
                            swizzledSelector,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

code

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,933评论 18 139
  • 这篇文章完全是基于南峰子老师博客的转载 这篇文章完全是基于南峰子老师博客的转载 这篇文章完全是基于南峰子老师博客的...
    西木阅读 30,636评论 33 466
  • 壹 今日小面积延误机场:杭州萧山、北京首都、重庆江北、上海浦东、成都双流、深圳宝安、昆明长水。 贰 湖北省鄂州市政...
    飞巴商旅阅读 123评论 0 0
  • 开学都快半个月了,我都还没有好好的去北大看看那可爱的妹妹。 周六起了个大早,把自己收拾打扮的特别的阳光,有点自恋。...
    胡先生你好阅读 138评论 0 0
  • 你喜欢什么口味的冰淇淋? 不知从什么时候开始,也不知什么原因,就不喜欢吃凉的东西了。雪糕,冰淇淋,加冰饮料,甚至凉...
    韩冰rabbit阅读 326评论 0 1