簡介
Protocol Buffer(簡稱Protobuf或PB)是由Google推出的一種數(shù)據(jù)交換格式.
與傳統(tǒng)的XML和JSON不同的是,它是一種二進制格式,免去了文本格式轉(zhuǎn)換的各種困擾,并且轉(zhuǎn)換效率也是非掣壹瑁快,由于它的跨平臺您没、跨編程語言的特點,讓它越來越普及,尤其是網(wǎng)絡數(shù)據(jù)交換方面日趨成為一種主流.
原理
對于json和xml最終在網(wǎng)絡傳輸時都是以字符串轉(zhuǎn)二進制的進行傳輸?shù)?使用的是utf8編碼格式,而PB在編碼與解碼上進行了改進,使數(shù)據(jù)包更小,所以我覺得可以把他當做一種壓縮格式.這里有一篇關(guān)于原理的博文,感興趣大家可以去看一看 Protocol Buffer 序列化原理大揭秘 - 為什么Protocol Buffer性能這么好盏求?
安裝
我們需要安裝PB的編譯器,將我們用PB語法格式創(chuàng)建的對象轉(zhuǎn)化為OC或Swift的對象,原來PB只支持Python,Java,C++,現(xiàn)在新的版本支持OC,Swift需要我們額外配置一下,期待以后的更新吧.這是github的鏈接
解壓縮后,cd到其目錄下執(zhí)行下面的終端命令進行安裝
$ ./autogen.sh
$ ./configure
$ make
$ make check
$ sudo install
安裝結(jié)束后,執(zhí)行 protoc --version ,若有顯示版本號,則表明安裝成功.若是要試用Swift則需要
$ brew install protobuf-swift
$ git clone https://github.com/alexeyxo/protobuf-swift.git
//cd到clone后的目錄
$ ./scripts/build.sh
接下來就是創(chuàng)建proto文件,將其翻譯為OC或Swift,所以先了解proto的語法
語法
接下來我只介紹些常用語法,這里有介紹語法比較詳細的博文 這是一份很有誠意的Protocol Buffer語法詳解 Protobuf3 語法指南
//表示使用的是PB3的語法
syntax = "proto3";
//message代表著一個數(shù)據(jù)結(jié)構(gòu),也就相當于一個類, 類名Person
message Person {
string name = 1;
int32 age = 2;
repeated int32 friends = 3;
//這里就相當于類中的屬性,string表示類型為字符串,name表示屬性名,數(shù)字1則是用來標識Person中的屬性,在編解碼時用到,使用從1遞增即可,這樣效率高些
}
對應到iOS的OC和Swift中,上面就包含了所需的基本數(shù)據(jù)類型了,一個message,其實就可以看做一個字典.至于數(shù)組就比較特別了,而是要在基本的數(shù)據(jù)結(jié)構(gòu)前 加上可復用的修飾符 repeated 就如上面的friends一樣.
編譯轉(zhuǎn)換
OC
進入proto文件目錄 執(zhí)行下面的命令
$ protoc --objc_out=./ ./test.proto
Swift
進入proto文件目錄 執(zhí)行下面的命令
$ mbp$ protoc --swift_out=./ ./test.proto
這樣就得到了,翻譯后所需的類文件了,接下來就要到項目中集成了
項目集成 在項目中使用PB需要使用第三方庫,可以使用CocoaPod集成
OC:
pod "Protobuf"
Swift:
pod 'ProtocolBuffers-Swift'
對于OC版本,拖進項目后要再做一些額外處理,生成的是MRC環(huán)境下的代碼,需要設置一下, 其次再編譯后會報一些錯誤,據(jù)我所知的處理方案是將其注釋掉(我了解到的是該方法在C99后失效了,至于為何這里還有,我也很無奈ㄟ( ▔, ▔ )ㄏ,到Github上反應了).這樣就可以使用了. 然后就是PB的序列化與反序列化
序列化與反序列化
OC
Person* p = [Person new];
p.name = @"南小鳥";
p.age = 18;
p.friendsArray = [GPBInt32Array array]; //這是里面的數(shù)組,其他方法可以點進去看
[p.friendsArray addValue:10];
NSString* jsonStr = @"{\"name\":\"南小鳥\",\"age\":18,\"friendsArray\":[10]}";
NSData* data = [p data]; //序列化
NSData* strData = [jsonStr dataUsingEncoding:(NSUTF8StringEncoding)];
NSLog(@"PB --> %ld JSON --> %ld",data.length,strData.length);
//反序列化
Person* res = [[Person alloc] initWithData:data error:nil];
NSLog(@"%@,%ld,%@",res.name,res.age,res.friendsArray);
運行結(jié)果:
PB --> 16 JSON --> 49
南小鳥,18,<GPBInt32Array 0x600000059200> { 10 }
Swift
//創(chuàng)建新的對象,通過Builder來進行創(chuàng)建,賦值.
let p = Person.Builder()
p.name = "南小鳥"
p.age = 18
p.friends = [10]
//getMessage可以得到該對象,然后將其序列化
let data = p.getMessage().data()
//將其反序列化,可能出錯,需要try
let res = try! Person.parseFrom(data: data)
優(yōu)缺點
優(yōu)點
1,數(shù)據(jù)壓縮效果好,序列化反序列速度快
2,跨平臺,生成一次proto文件,多端使用
缺點
1,可讀性行差(在代碼中)
2,最增加App包體積(生成的類本身就代碼很多,而且需要使用第三方庫)
3,用的人少(在項目交接時,還需要學習這方面的知識)