簡介:
protobuf 即 google protocol buffer 是一種數據封裝格式協議;
比如其他經常用的xml,json等格式;protobuf的優勢是效率高,同樣的一份數據使用protobuf存儲的時候更小,更加方便;
官網:
https://developers.google.com/protocol-buffers/
https://github.com/google/protobuf
在iOS上的使用
目前最新的版本需要xcode7.0+,以及不支持ARC
1. 從github上面下載全部代碼
2. 在mac上編譯protobuf 可能還需要 autoconf,libtool,automake,
請先在mac上安裝這三個依賴庫;使用brew安裝就行
brew install autoconf
brew install libtool
brew install automake
automake的安裝可能會連接到被牆的網站,這時從網上找一份谷歌host即可;
3. 解壓下載的 protobuf-master, 並打開終端入 /protobuf-master/objectivec/DevTools/ 目錄
執行 sudo sh full_mac_build.sh
等待編譯完成,如果遇到錯誤可能是上面3個依賴或是別的依賴沒有安裝,排查一下就好
4. 安裝完成之后,即會在 protobuf-master/src/ 目錄下生成 protoc 可執行程序
以后我們需要用該生成把 .proto文件生成對應平台的代碼;
5. 如下安裝protobuf定義的proto3語法生成一份測試用的數據格式,Person.proto文件
syntax = "proto3"; message Person { string name = 1; int32 age = 2; string address = 3; }
6. 使用 protoc 將 .proto文件 生成對應平台的代碼;這里生成oc的代碼
如下protoc命令的幫助

Parse PROTO_FILES and generate output based on the options given: -IPATH, --proto_path=PATH Specify the directory in which to search for imports. May be specified multiple times; directories will be searched in order. If not given, the current working directory is used. --version Show version info and exit. -h, --help Show this text and exit. --encode=MESSAGE_TYPE Read a text-format message of the given type from standard input and write it in binary to standard output. The message type must be defined in PROTO_FILES or their imports. --decode=MESSAGE_TYPE Read a binary message of the given type from standard input and write it in text format to standard output. The message type must be defined in PROTO_FILES or their imports. --decode_raw Read an arbitrary protocol message from standard input and write the raw tag/value pairs in text format to standard output. No PROTO_FILES should be given when using this flag. -oFILE, Writes a FileDescriptorSet (a protocol buffer, --descriptor_set_out=FILE defined in descriptor.proto) containing all of the input files to FILE. --include_imports When using --descriptor_set_out, also include all dependencies of the input files in the set, so that the set is self-contained. --include_source_info When using --descriptor_set_out, do not strip SourceCodeInfo from the FileDescriptorProto. This results in vastly larger descriptors that include information about the original location of each decl in the source file as well as surrounding comments. --dependency_out=FILE Write a dependency output file in the format expected by make. This writes the transitive set of input file paths to FILE --error_format=FORMAT Set the format in which to print errors. FORMAT may be 'gcc' (the default) or 'msvs' (Microsoft Visual Studio format). --print_free_field_numbers Print the free field numbers of the messages defined in the given proto files. Groups share the same field number space with the parent message. Extension ranges are counted as occupied fields numbers. --plugin=EXECUTABLE Specifies a plugin executable to use. Normally, protoc searches the PATH for plugins, but you may specify additional executables not in the path using this flag. Additionally, EXECUTABLE may be of the form NAME=PATH, in which case the given plugin name is mapped to the given executable even if the executable's own name differs. --cpp_out=OUT_DIR Generate C++ header and source. --csharp_out=OUT_DIR Generate C# source file. --java_out=OUT_DIR Generate Java source file. --javanano_out=OUT_DIR Generate Java Nano source file. --js_out=OUT_DIR Generate JavaScript source. --objc_out=OUT_DIR Generate Objective C header and source. --php_out=OUT_DIR Generate PHP source file. --python_out=OUT_DIR Generate Python source file. --ruby_out=OUT_DIR Generate Ruby source file.
生成OC代碼格式命令
D/protoc --proto_path=A --objc_out=B C/Person.proto
D: 表示 protoc 可執行程序的目錄
A:表示處理proto文件需要的目錄,和生成目錄一樣就行
B:表示生成代碼的文件,oc會成生.h和.m 這里就是指生成文件需要放的目錄
C:表示需要的.proto文件,即protoc會根據此文件里面定義的格式生成相應平台代碼文件
生成之后的oc,.h 和 .m 就可以放到xcode工程里面使用了,不支持ARC,ARC的工程對此.m添加 -fno-objc-arc
7. 這里使用xcode7.3創建了DEMO工程,GPBDemo,並設置工程為 mrc
把第6步生成的Person.pbobjc.h,Person.pbobjc.m 導入工程
把 protobuf-master/objectivec/ 目錄下面所有的 .h 和.m 手動導入工程,把該目錄下的google文件也會部導入工程
在工程設置 header search path 添加 $(PROJECT_DIR)/GBPDemo , 不然導入上面的google文件夾之后編譯會出頭文件連接錯誤;
把GPBProtocolBuffers.m 從工程里面刪除掉(這里是官網說的https://github.com/google/protobuf/tree/master/objectivec)
導入之后的工程結構如下
以上配置完成之后,編譯就正常通過了
8. 測試使用protobuf
在工程ViewController.m 里面導入
#import "GPBProtocolBuffers.h"
#import "Person.pbobjc.h"
如下代碼
Person *pe = [[Person alloc]init]; pe.name = @"jobs"; pe.age = 86; pe.address = @"Beijing"; //以下是效率對比 //protocbufer NSLog(@"protocbufer: %@",pe); NSLog(@"%lu",[pe data].length); //json NSDictionary *pj = @{@"name":@"jobs", @"age":@86, @"address":@"Beijing"}; NSData *jsd = [NSJSONSerialization dataWithJSONObject:pj options:0 error:nil]; NSLog(@"JSON: %@",pj); NSLog(@"%lu", jsd.length); //xml NSString *xml = @"<name>jobs</name><age>86</age><address>Beijing</address>"; NSData *xmlData = [xml dataUsingEncoding:NSUTF8StringEncoding]; NSLog(@"XML: %@",xml); NSLog(@"%lu",xmlData.length); [pe release];
執行結果:
從上可以看出:
同樣的數據:
protubuf:占17個字節
json: 44個字節
xml:56個字節
以上就是效率上的測試使用
9. 總結
數據按照protobuf封裝可以通過網絡傳給后台,后台同樣使用protobuf處理;
會非常的方便的高效;后台定義一份proto數據格式,然后生成其他平台的代碼,集成調用非常的方便,也偏於維護和擴展;
更新關於protobuf的數據格式,組合語法可以參考官方文檔說明
10:上述的 iOS 示例工程
https://github.com/cocoajin/TDDDemo/tree/master/GBPDemo
protobuf靜態類庫方式 demo https://github.com/cocoajin/TDDDemo/tree/master/PGBlibT
參考:
https://github.com/google/protobuf
http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/
https://my.oschina.net/kgdugyiy/blog/538333