美文网首页PBpb
ios 中(data) protocol buffer, Jso

ios 中(data) protocol buffer, Jso

作者: jianshudxw | 来源:发表于2018-12-11 16:22 被阅读0次

    前言

    前些天,程序出现了一个bug:数据莫名的丢失。由于业务复杂,折腾了好久才解决,在网上也没有找的答案, 故,记下来。

    现象

    1. 将 protobuf 的 Data 转换为 Json
    2. Json 转为 Model
    3. 发现 Model 的有些字段数据丢失
    4. 发现是有 Has* 对应的 字段变为nil了
    5. 这个问题发生在32位真机上。

    知识点

    • protobuf 提供了 Data 与 Model 互转的方法
    • protobuf 没有提供 Json 和 Model 互转的方法(ios 上我没有找到,有找到的麻烦通知一声)
    • 32位机和64位机在遍历Dictionary时可的顺序不一样。(具体还没有深入研究)
    • protobuf 在转Model时 会为 Message 嵌套 属性 添加 has* 字段,为数组添加_count字段 (阅读源码发现有这个SEL hasOrCountSel_ 私有变量控制,且这两个新增加的属性的赋值会影响到对应的字段

    例如

    Message *msg = (一个有数据的msg)
    content 是嵌套的Message
    NSLog(@"msg.content = ",msg.content)
    //有数据
    msg.hasContent = YES;
    NSLog(@"msg.content = ",msg.content)
    //打印msg.content =nil
    
    

    修改方案

    本着不修改第三方库的原则,项目中使用了 YYModel。添加了个分类 GPBMessage (YYModel) 在 Json 转Model 时过滤掉has_count 先这样解决了问题。

    - (NSString *)uppercaseFirstCharacter:(NSString*)str {
        NSRange range = NSMakeRange(0,1);
        NSString *upperFirstCharacter = [[str substringToIndex:1] uppercaseString];
        return [str stringByReplacingCharactersInRange:range withString:upperFirstCharacter];
    }
    
    - (NSDictionary *)modelCustomWillTransformFromDictionary:(NSDictionary *)dic {
        NSMutableDictionary *filteredDic = [[NSMutableDictionary alloc] initWithDictionary:dic];
        GPBDescriptor *descriptor = [self descriptor];
        for (GPBFieldDescriptor *fd in descriptor.fields) {
            Ivar ivar = class_getInstanceVariable([fd class], "hasOrCountSel_");
            //         当使用ARC后请使用  BOOL ok = NO; ok = object_getIvar(fd, ivar);
            //         https://stackoverflow.com/questions/8356232/object-getivar-fails-to-read-the-value-of-bool-ivar
            unsigned char val;
            val = ((unsigned char (*)(id, Ivar))object_getIvar)(fd, ivar);
            //         RCTrace(@"Looks like I got: %u (or character %c) %@", val, val,fd.name);
            if (val != 0 ) {
                NSString *countKey = [NSString stringWithFormat:@"%@_Count",fd.name];
                [filteredDic removeObjectForKey:countKey];
                NSString *hasKey = [NSString stringWithFormat:@"has%@",[self uppercaseFirstCharacter:fd.name]];
                [filteredDic removeObjectForKey:hasKey];
            }
        }
        return filteredDic;
    }
    

    相关文章

      网友评论

        本文标题:ios 中(data) protocol buffer, Jso

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