protobuf3.0之后已經(jīng)很好用了,swift版也有,但網(wǎng)上教程很多已經(jīng)很老了,不適用了,所以寫個(gè)新的
總的過程是3步:
1.編譯安裝.proto格式轉(zhuǎn)換器;
2.引入相應(yīng)版本的protobuf(多用CocoaPods);
3.命令行轉(zhuǎn)換成OC或swift文件并拖入項(xiàng)目中;
第一步alexeyxo大神(方法二)用了Homebrew全自動(dòng)安裝,最方便,蘋果(方法三)和谷歌(方法一)的需要手動(dòng)輸入命令,蘋果還要手動(dòng)放到/usr/local/bin/
目錄下,較為復(fù)雜,不過目前蘋果正在快速更新,估計(jì)以后就更好用了
方法一:安裝編譯google官方的OC, protobuf3.0以后
參考文章http://blog.csdn.net/mtc1256/article/details/52180929
- 編譯和安裝
直接在https://github.com/google/protobuf/releases 找到已經(jīng)編譯好的objectivec版本下載就行了.
下載好之后開始安裝
cd protobuf-3.0.0
./configure
make -j8
sudo make install
驗(yàn)證是否安裝成功
$ which protoc
/usr/local/bin/protoc
- 用pod引入項(xiàng)目中
pod 'Protobuf', '~> 3.2.0'
- 寫一個(gè)測試腳本生成proto代碼
Person.proto
syntax = "proto3";
package com.xxx;
option swift_prefix = "TCC";//swift類前綴,適用于方法三
option objc_class_prefix = "TCC";//OC類前綴,適用于方法一
message Person{
string name = 1;
int32 level = 2;
string icon = 3;
}
或者proto2語法
syntax = "proto2";
message Person {
required string name = 1;
required int32 level = 2;
required string icon = 3;
}
代碼直接生成.h和.m
舉例:cd進(jìn)入Person.proto所在的文件夾下,執(zhí)行命令
protoc --objc_out=. Person.proto
然后在gen文件夾下就會(huì)生成Person.pbobjc.h和Person.pbobjc.m文件谴餐。
protobuf為了性能考慮,創(chuàng)建的都是mrc文件,因此在build phrases ->Compile
sources中給拖入的文件添加 -fno-objc-arc的標(biāo)志
- 簡單使用
//創(chuàng)建,直直接賦值
Person *myPerson = [Person alloc] init];
myPerson.name = @"xu";
myPerson.level = 4;
myPerson.icon = @"123.jpg";
//得到data
NSData *data = myPerson.data;
NSLog(@"%@",data);
//從data得到模型
NSError *error = nil;
Person *myPerson2 = [Person parseFromData:data error:&error];
NSLog(@"%@",myPerson2.description);
方法二:使用別人編譯好的,包括OC,swift
參考http://www.cnblogs.com/akforsure/p/5190187.html
github上有大神提供了編譯好的OC和swift版protobuf.由于目前谷歌官方在3.0版本后已經(jīng)提供了OC版,所以只有swift版還在更新
地址里面也有操作步驟說明https://github.com/alexeyxo
推薦使用Homebrew自動(dòng)安裝+pod引用的方式
- 安裝編譯
利用Homebrew自動(dòng)安裝(建議使用)
1.ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
2.brew install protobuf-swift
或手動(dòng)編譯
1.ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
2.brew install automake
3.brew install libtool
4.brew install protobuf
5.git clone git@github.com:alexeyxo/protobuf-swift.git
6../scripts/build.sh
- 編譯安裝后引入項(xiàng)目中
手動(dòng)添加 ./src/ProtocolBuffers/ProtocolBuffers.xcodeproj 到自己的項(xiàng)目
也可以使用pod方式(建議使用)
use_frameworks!
pod 'ProtocolBuffers-Swift'
- 輸出到當(dāng)前目錄
cd到Person.proto目錄,運(yùn)行下列,得到Person.proto.swift文件,拖入項(xiàng)目中即可
protoc Person.proto --swift_out="./"
- 簡單使用
//創(chuàng)建:用builder賦值,得到的是Person.Builder類,不是模型
let myPersonBuilder = Person.Builder()
myPersonBuilder.name = "coderXu"
myPersonBuilder.level = 100
myPersonBuilder.icon = "123.png"
//轉(zhuǎn)成data,需要用到build()來得到真正的模型person實(shí)例
guard let myPerson = try? myPersonBuilder.build() else { return }
let data = myPerson.data()
//從data轉(zhuǎn)回來
let myPerson2 = try? Person.parseFrom(data: data)
print(myPerson2.name)
print(myPerson2.level)
print(myPerson2.icon)
方法三:使用蘋果官方提供的swift版
參考https://github.com/apple/swift-protobuf
需要注意:如果已經(jīng)使用了方法二的第三方swift版,需要執(zhí)行brew uninstall protobuf-swift卸載掉
否則會(huì)和蘋果官方的swift轉(zhuǎn)換工具沖突,因?yàn)閮蓚€(gè)都叫protoc-gen-swift,但是轉(zhuǎn)換出來的格式不一樣,蘋果官方得到的叫Person.pb.swift,而第三方的叫Person.proto.swift,而且會(huì)報(bào)錯(cuò)import ProtocolBuffers找不到no such module ProtocolBuffers
- 編譯和安裝
先下載,進(jìn)入,列出tag,切換到對(duì)應(yīng)分支,然后build
$ git clone https://github.com/apple/swift-protobuf.git
$ cd swift-protobuf
$ git tag -l
$ git checkout tags/[tag_name]
$ swift build
然后進(jìn)入.build/debug文件夾下,找到protoc-gen-swift,這是一個(gè)可執(zhí)行文件,復(fù)制一份放到系統(tǒng)的PATH環(huán)境目錄下,在mac也就是磁盤/usr/local/bin下面
其中protoc是方法一谷歌生成OC版轉(zhuǎn)換器
需要注意:如果已經(jīng)使用了方法二的第三方swift版,需要先執(zhí)行brew uninstall protobuf-swift卸載掉
否則會(huì)和蘋果官方的swift轉(zhuǎn)換工具沖突,因?yàn)閮蓚€(gè)都叫protoc-gen-swift,但是轉(zhuǎn)換出來的格式不一樣,蘋果官方得到的叫Person.pb.swift,而第三方的叫Person.proto.swift,而且會(huì)報(bào)錯(cuò)import ProtocolBuffers找不到no such module ProtocolBuffers
- 引入項(xiàng)目
推薦用pod,pod install
pod 'SwiftProtobuf'
- 轉(zhuǎn)換輸出
cd到Person.proto目錄,運(yùn)行下列系統(tǒng)會(huì)自動(dòng)PATH環(huán)境目錄下的protoc-gen-swift轉(zhuǎn)換,得到Person.pb.swift文件,拖入項(xiàng)目中即可
protoc --swift_out=. Person.proto
- 簡單使用
//直接初始化一個(gè)Person實(shí)例
var myPerson = Person()
//賦值
myPerson.name = "sss"
myPerson.level = 4
myPerson.icon = "444.jpg"
print(myPerson)
//默認(rèn)情況下,要求必須有值時(shí)(required),如果賦值不完整時(shí),這一步會(huì)報(bào)錯(cuò)
guard let data = try? myPerson.serializedData() else {print("error") return}
print("========serializedData=\(data)")
guard let myPerson2 = try? Person(serializedData: data) else {
print("error")
return
}
print(myPerson2)
//要求必須有值時(shí)(required),賦值不完整時(shí)也可以通過參數(shù)partial: true來強(qiáng)制轉(zhuǎn)換出來
guard let data2 = try? myPerson.serializedData(partial: true) else {print("error")
return}
print("========serializedData=\(data2)")
//同理,data2中的數(shù)據(jù)不完整也可以通過參數(shù)partial: true來強(qiáng)制轉(zhuǎn)換出來
guard let myPerson3 = try? person(serializedData: data2, partial: true) else {
print("error")
return
}
print(myPerson3)
//json格式字符串初始化,可以將字典序列化為Data后再轉(zhuǎn)換為String得到
let jsonString = "{\"name\":\"xu\",\"icon\":\"321.jpg\",\"level\":2}"
//Person(jsonString: jsonString)
//Person(textFormatString: textString)
//創(chuàng)建:得到模型
guard var myPerson = try? Person(jsonString: jsonString) else {
print("error")
return
}
//修改
myPerson.icon = "li.png"
print(myPerson)
//得到Protocol Buffer二進(jìn)制序列化的data,一般用來傳輸
guard let data = try? myPerson.serializedData() else {
print("error")
return}
print("=========\(data)")
//從Protocol Buffer二進(jìn)制序列化data 得到模型
guard let myPerson2 = try? Person(serializedData: data) else {
print("error")
return
}
print(myPerson2)
//textFormatString格式示例,中間用\n或空格分隔
let textString = "name:\"xu\" icon:\"321.jpg\" level:2"
//得到myPerson模型
guard var myPerson = try? Person(textFormatString: textString) else {
print("error")
return
}
//修改模型
myPerson.icon = "li.png"
print(myPerson)
//得到UTF-8 JSON序列化的data,這樣沒用到protobuf,是用iOS的JSON serialization轉(zhuǎn)換的data,一般用來內(nèi)部使用
guard let data2 = try? myPerson.jsonUTF8Data() else {print("error")
return}
print("========jsonUTF8Data=\(data2)")
//從UTF-8 JSON序列化的data 得到模型
guard let myPerson3 = try? Person(jsonUTF8Data: data2) else {
print("error")
return
}
print(myPerson3)
最后,protobuf的textFormat格式舉例:
文件定義test.proto:
//學(xué)生模型
message student{
required string name = 1; //姓名
required int32 age = 2; //年齡
optional string addr = 3;
}
//班級(jí)模型,包含班級(jí)名和學(xué)生
message class{
required string name = 1; //班級(jí)名稱
repeated student member = 2; //班級(jí)成員
}
初始化時(shí)的textFormat格式應(yīng)為
name: "Communication 2004"
member {
name: "flyan338"
age: 26
addr: "china"
}
member {
name: "likeliu"
age: 25
addr: "china"
}
member {
name: "gaoy"
age: 24
addr: "American"
}
這份配置表明:一個(gè)叫做 "Communication 2004"的班級(jí)偶摔,有3個(gè)student昭躺,你可以直接用protobuf來load出來