一.前言介绍
为避免后续接入 protobuf 功能的iOS开发人员少走弯路,整理了相关文档供参考!!!
1.背景简介
ProtoBuf (Google Protocol Buffer)是由google公司用于数据交换的序列结构化数据格式,具有跨平台、跨语言、可扩展特性,类型于常用的XML及JSON,但具有更小的传输体积、更高的编码、解码能力,特别适合于数据存储、网络数据传输等对存储体积、实时性要求高的领域。以 .proto为后缀,有自己的编译器 protoc, protoc2 和 protoc3 版本
2.主要用途
主要用于结构化数据串行化的灵活、高效、自动的方法,有如XML,不过他更小,更快,也更简单。你可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构。甚至可以在无需重新部署程序的情况下更新数据结构。
3.时间复杂度
时间开销: XML格式化(序列化)的开销还好;但是XML解析(反序列化)的开销就不敢恭维了。 但是protobuf在这个方面就进行了优化。可以使序列化和反序列化的时间开销都减短。
4.空间复杂度
空间开销:protobuf相比其他传输也减少了很多。
5.兼容性
支持向后兼容和向前兼容,也就是说当客户端和服务器同时使用一块协议的时候, 当客户端在协议中增加一个字节,并不会影响客户端的使用
二.环境搭建
1.下载protobuf
使用git的方式到开源社区下载protobuf,在终端种输入以下命令:
git clone https://github.com/google/protobuf.git
2.安装brew
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
此处会下载多个插件,大概需要执行3-5分钟左右
PS:执行这一步的时候可能会error443 connect报错,这个时候你不要心慌,只需将mac上的终端大退重新从第一步开始执行就ok了,亲测可以!!!
3.使用brew安装protoc
brew install protobuf
4.安装 automake
brew install automake
brew install libtool
5.将ProtoBuf协议文件编译为OC文件
protoc --proto_path=. --objc_out=. UpDriverPosition.proto
protoc 为proto的生成指令 后面添加 参数
参数的形式为: --参数命令名=参数
--proto_path=. 指出proto文件所在的根目录是哪里, 如果用.说明是当前目录
--objc_out=. 指出 生成目录在哪里, 如果用.说明是当前目录
最后跟 proto文件的名称,
需要注意的事 proto 里面需要指出pb语法的版本; 如 syntax = "proto2"; 有 optional 关键字 说明是 proto2版本
生成的.h语.m文件 只能使用OC的MRC模式,暂时不支持ARC.所以刚添加到项目 报错很正常.
三.通过cocopods安装Protobuf插件
在prodfile加入 pod 'Protobuf', '3.11.4'
执行pod setup ----> pod install 这里看个人习惯执行命令就好了(关于cocopods安装和命令处理这里不过多解释)
执行完以后Pods下面会多出一个Protobuf文件,就可以愉快的上代码了
四.demo核心代码
在Person.proto中写入:
syntax = "proto3";
message Person {
string name = 1;
int64 age = 2;
string gender = 3;
}
终端执行命令生成 .h. .m文件,将文件拖拽到工程中后续使用
#import "ViewController.h"
#import "Person.pbobjc.h"
@interface ViewController ()
@property (nonatomic, strong) Person *person;
@end
@implementation ViewController
#pragma mark - Life Cycle
- (void)viewDidLoad {
[super viewDidLoad];
[self testProtobuf];
}
- (void)testProtobuf {
NSLog(@"%@", self.person);
NSData *personData = [self encode:self.person];
NSLog(@"%@", personData);
Person *decodeObj = [self decode:personData];
NSLog(@"%@", decodeObj);
decodeObj.name = @"Tom";
NSLog(@"%@", decodeObj);
}
#pragma mark - Private Methods
- (nullable NSData *)encode:(Person *)person {
return [person data];
}
- (nullable Person *)decode: (nonnull NSData *)data {
return [Person parseFromData:data error:nil];
}
#pragma mark - Lazy Methods
- (Person *)person {
if (!_person) {
_person = [Person new];
_person.name = @"Carson";
_person.age = 27;
_person.gender = @"Male";
}
return _person;
}
@end