还在用JSON? Google Protocol Buffers 更快更小 (实践篇)

欢迎关注微信公众号「随手记技术团队」,查看更多随手记团队的技术文章。转载请注明出处
本文作者:丁同舟
原文链接:mp.weixin.qq.com/s/y0dyK47_s…

背景

由于随手记客户端与服务端交互的过程中,对部分数据的传输大小和效率有较高的要求,普通的数据格式如 JSON 或者 XML 已经不能满足,因此决定采用 Google 推出的 Protocol Buffers 以达到数据高效传输。

介绍

Protocol buffers 为 Google 提出的一种跨平台、多语言支持且开源的序列化数据格式。相对于类似的 XML 和 JSON,Protocol buffers 更为小巧、快速和简单。其语法目前分为proto2proto3两种格式。

目前 Google 官方的 Protobuf 最新 release 版本为3.5.1,以下都是基于此版本的环境搭建。

关于 Protocol Buffer 的使用可以查阅官方文档

准备工作

环境要求

  • Objective-C 2.0 Runtime (32bit & 64bit iOS, 64bit OS X)
  • Xcode 7.0+

Note

Protobuf 出于性能考虑没有使用 ARC,但在 ARC 下是可以使用的

安装

  1. 下载 Protobuf 代码包,这里选择 protobuf-objectivec-3.5.1.tar.gz

  2. 解压代码包

  3. 编译 Protobuf,这里可能需要安装部分工具:

$ brew install autoconf
$ brew install automake
$ brew install libtool
复制代码
  1. 运行下面脚本进行编译
$ ./autogen.sh
$ ./configure
$ make
$ make install
复制代码
  1. 检查protobuf是否安装成功
$ protoc --version
复制代码

如果成功打印版本号则安装成功

libprotoc 3.5.1
复制代码

在 iOS 中使用 Protobuf

创建.proto文件

这里使用官方文档上的一份示例数据结构创建Person.proto

syntax = "proto3";

message Person {
  string name = 1;
  int32 id = 2;
  string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    string number = 1;
    PhoneType type = 2;
  }

  repeated PhoneNumber phone = 4;
}
复制代码

使用命令行编译Person.protoobjective-c的文件,编译出来的文件为Person.pbobjc.hPerson.pbobjc.m

protoc Person.proto --objc_out=./
复制代码
引入 Protobuf 运行时资源

Google 官方的文档提供了两种引入方式,但使用第一种的时候编译不能通过,所以这里选择了第二种:

复制protobuf目录下的objectivec/*.h, objectivec/google/protobuf/*.pbobjc.h, objectivec/google/protobuf/*.pbobjc.m, 以及除去objectivec/GPBProtocolBuffers.m后的objectivec/*.m

这里直接用命令行操作,首先进入protobufobjectivec的目录:

 $ cd protobuf-3.5.1/objectivec
复制代码

然后复制符合规则的文件到指定的工程目录下:

$ mkdir ~/ProtobufDemo/ProtocolBuffers ~/ProtobufDemo/ProtocolBuffers/google ~/ProtobufDemo/ProtocolBuffers/google/protobuf
$ cp *.h *.m ~/ProtobufDemo/ProtocolBuffers
$ cp google/protobuf/*.pbobjc.h google/protobuf/*.pbobjc.m ~/ProtobufDemo/ProtocolBuffers/google/protobuf

复制代码

Note

上面的命令并没有排除 GPBProtocolBuffers.m 文件,引入时需要手动排除

现在把ProtocolBuffers目录下所有文件以及上面编译出来的Person.pbobjc.hPerson.pbobjc.m都引入到工程中

现在工程目录结构大概是长这样

需要注意,由于protobuf没有使用 ARC,因此需要为所有.m文件加上-fno-objc-arc来关闭 ARC

Note

需要注意工程中的 Header Search Paths 要增加 $(PROJECT_DIR)/ProtocolBuffers(具体的路径视情况而定)

直接引入 ProtocolBuffers 工程

如果觉得手动引入文件的方式过于复杂,可以直接引入ProtocolBuffers工程作为依赖项

  1. 进入解压后的protobuf目录下,复制objective目录下的所有文件到ProtobufDemo/ProtocolBuffers目录下

  2. ProtobufDemo工程中引入ProtocolBuffers_iOS工程

  3. Build Phases中加入依赖关系并链接库

  4. 引入Person.pbobjc.hPerson.pbobjc.m文件并为.m加上-fno-objc-arc

  5. 修改工程配置中部分路径为 $(PROJECT_DIR)/ProtocolBuffers

测试

首先引入头文件

#import "Person.pbobjc.h"
复制代码

生成Person对象并进行编码和解码

Person *p = [[Person alloc] init];
p.id_p = 1;
p.name = @"person1";
p.email = @"123@qq.com";

//encode
NSData *data = [p data];
NSLog(@"Protocol Buffers:\n%@\nData: %@\nData Length: %lu", p, data, data.length);

//decode
Person *newP = [[Person alloc] initWithData:data error:nil];
NSLog(@"Decoded: %@", newP);
复制代码

运行程序,打印日志如下:

Protocol Buffers:
<Person 0x60c0000da2b0>: {
    name: "person1"
    id: 1
    email: "123@qq.com"
}
Data: <0a077065 72736f6e 3110011a 0a313233 4071712e 636f6d>
Data Length: 23

Decoded: <Person 0x6040000d9c90>: {
    name: "person1"
    id: 1
    email: "123@qq.com"
}
复制代码

Coffee time!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值