• 2013-06-12

    遍历NSString每一个字符的正确方式!

    Views: 29110 | No Comments

    最近在处理Cocoa NSString时, 遇到一些字符编码的问题, 从而引出一个遍历NSString每一个字符的"正确"方式! 很有趣.

    NSString是UTF-16编码的, 也就是16位的unichar字符的序列. 所以, 一般遍历其每一个字符的方法就是:

    for(int i=0; i<str.length; i++){
        unichar ch = [str characterAtIndex: i];
    }
    

    但是, 我们平常书写的字符, 并不全部都是用唯一的一个16位字符来表示, 而是有一部分用两个16位字符来表示, 这就是surrogate pairs的概念. 如果还是用上面的方法遍历字符串, 就会出现"断字". 例如图中这个Apple Color Emoji的"THUMBS UP SIGN"字符, 其实是用2个16位unichar来表示, 它的Unicode是U+1F44D, 用(U+D83D U+DC4D)两个字符来表示.

    还好, NSString的rangeOfComposedCharacterSequencesForRange:rangeOfComposedCharacterSequenceAtIndex:两个方法可以用来处理这种情况. 所以, 真正正确的遍历NSString的每一个字符的方法就是这样了:

    NSRange range;
    for(int i=0; i<str.length; i+=range.length){
        range = [str rangeOfComposedCharacterSequenceAtIndex:i];
        NSString *s = [str attributedSubstringFromRange:range];
    }
    

    一次遍历一个子串, 而不是遍历一个unichar了.

    相关资料:

    Posted by ideawu at 2013-06-12 12:26:39
  • 2013-04-14

    Cocoa处理JSON转换, 兼谈计算机语言的哲学

    Views: 19902 | 3 Comments

    用了下 Objective-C Cocoa 里的 JSON 相关类 NSJSONSerialization, 发现简单的事情突然变得太复杂了. 想想用 php 语言的时候, 如果想把 php 语言对象转成字符串, 直接 json_encode(); 如果想把网络或者文件中的一段二进制数据(JSON 字符串)转成 php 对象, 直接 json_decode().

    但是, 在 Cocoa 里就不那么直接了. 首先, 你会遇到字符编码的问题, 所以你得到的和操作的不能是字符串, 而是 NSData. 其次, NSJSONSerialization 无谓地增加了限制, 顶层 Objective-C 对象只能是数组和字典.

    我不想探讨这里面的原因, 我当然知道这里面的原因, 我只是说, 这些原因可以避免.

    第一, 为解决后一个限制, 我可以做一些封装, 支持语言的整数对象和字符串对象(非常重要)直接转成 JSON 字符串, 而忽略所谓的 NSData(后面讲为什么 NSData 不是一个好东西).

    Continue reading »

    Posted by ideawu at 2013-04-14 15:51:29
|<<<1234>>>| 4/4 Pages, 20 Results.