美文网首页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