iOS引入google ProtocolBuffer(protobuf3)

protobuf3.0之后已经很好用了,swift版也有,但网上教程很多已经很老了,不适用了,所以写个新的

总的过程是3步:
1.编译安装.proto格式转换器;
2.引入相应版本的protobuf(多用CocoaPods);
3.命令行转换成OC或swift文件并拖入项目中;

第一步alexeyxo大神(方法二)用了Homebrew全自动安装,最方便,苹果(方法三)和谷歌(方法一)的需要手动输入命令,苹果还要手动放到/usr/local/bin/目录下,较为复杂,不过目前苹果正在快速更新,估计以后就更好用了

方法一:安装编译google官方的OC, protobuf3.0以后

参考文章http://blog.csdn.net/mtc1256/article/details/52180929

下载好之后开始安装

cd protobuf-3.0.0
./configure
make -j8
sudo make install

验证是否安装成功

$ which protoc
/usr/local/bin/protoc
  • 用pod引入项目中
pod 'Protobuf', '~> 3.2.0'
  • 写一个测试脚本生成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进入Person.proto所在的文件夹下,执行命令

protoc  --objc_out=. Person.proto

然后在gen文件夹下就会生成Person.pbobjc.h和Person.pbobjc.m文件。
protobuf为了性能考虑,创建的都是mrc文件,因此在build phrases ->Compile
sources中给拖入的文件添加 -fno-objc-arc的标志

  • 简单使用
//创建,直直接赋值
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版本后已经提供了OC版,所以只有swift版还在更新
地址里面也有操作步骤说明https://github.com/alexeyxo

推荐使用Homebrew自动安装+pod引用的方式

  • 安装编译
    利用Homebrew自动安装(建议使用)
1.ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
2.brew install protobuf-swift

或手动编译

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
  • 编译安装后引入项目中
    手动添加 ./src/ProtocolBuffers/ProtocolBuffers.xcodeproj 到自己的项目
    也可以使用pod方式(建议使用)
use_frameworks!
pod 'ProtocolBuffers-Swift'
  • 输出到当前目录
    cd到Person.proto目录,运行下列,得到Person.proto.swift文件,拖入项目中即可
protoc  Person.proto --swift_out="./"
  • 简单使用
//创建:用builder赋值,得到的是Person.Builder类,不是模型
let myPersonBuilder = Person.Builder()
myPersonBuilder.name = "coderXu"
myPersonBuilder.level = 100
myPersonBuilder.icon = "123.png"
        
//转成data,需要用到build()来得到真正的模型person实例
guard let myPerson = try? myPersonBuilder.build() else { return }
let data = myPerson.data()

//从data转回来
let myPerson2 = try? Person.parseFrom(data: data)
print(myPerson2.name)
print(myPerson2.level)
print(myPerson2.icon)

方法三:使用苹果官方提供的swift版

参考https://github.com/apple/swift-protobuf

需要注意:如果已经使用了方法二的第三方swift版,需要执行brew uninstall protobuf-swift卸载掉
否则会和苹果官方的swift转换工具冲突,因为两个都叫protoc-gen-swift,但是转换出来的格式不一样,苹果官方得到的叫Person.pb.swift,而第三方的叫Person.proto.swift,而且会报错import ProtocolBuffers找不到no such module ProtocolBuffers

  • 编译和安装
    先下载,进入,列出tag,切换到对应分支,然后build
$ git clone https://github.com/apple/swift-protobuf.git
$ cd swift-protobuf
$ git tag -l
$ git checkout tags/[tag_name]
$ swift build

然后进入.build/debug文件夹下,找到protoc-gen-swift,这是一个可执行文件,复制一份放到系统的PATH环境目录下,在mac也就是磁盘/usr/local/bin下面
其中protoc是方法一谷歌生成OC版转换器


WX20170515-230043@2x.png

需要注意:如果已经使用了方法二的第三方swift版,需要先执行brew uninstall protobuf-swift卸载掉
否则会和苹果官方的swift转换工具冲突,因为两个都叫protoc-gen-swift,但是转换出来的格式不一样,苹果官方得到的叫Person.pb.swift,而第三方的叫Person.proto.swift,而且会报错import ProtocolBuffers找不到no such module ProtocolBuffers

  • 引入项目
    推荐用pod,pod install
pod 'SwiftProtobuf'
  • 转换输出
    cd到Person.proto目录,运行下列系统会自动PATH环境目录下的protoc-gen-swift转换,得到Person.pb.swift文件,拖入项目中即可
protoc --swift_out=.  Person.proto
  • 简单使用
//直接初始化一个Person实例
var myPerson = Person()
//赋值
myPerson.name = "sss"
myPerson.level = 4
myPerson.icon = "444.jpg"
print(myPerson)
//默认情况下,要求必须有值时(required),如果赋值不完整时,这一步会报错
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)
//要求必须有值时(required),赋值不完整时也可以通过参数partial: true来强制转换出来
guard let data2 = try? myPerson.serializedData(partial: true) else {print("error")
     return}
print("========serializedData=\(data2)")
//同理,data2中的数据不完整也可以通过参数partial: true来强制转换出来
guard let myPerson3 = try? person(serializedData: data2, partial: true) else {
     print("error")
     return
}
print(myPerson3)
//json格式字符串初始化,可以将字典序列化为Data后再转换为String得到
let jsonString = "{\"name\":\"xu\",\"icon\":\"321.jpg\",\"level\":2}"
//Person(jsonString: jsonString)
//Person(textFormatString: textString)
//创建:得到模型
guard var myPerson = try? Person(jsonString: jsonString) else {
     print("error")
    return
}
//修改
myPerson.icon = "li.png"
print(myPerson)

//得到Protocol Buffer二进制序列化的data,一般用来传输
guard let data = try? myPerson.serializedData() else {
    print("error")
    return}
print("=========\(data)")
//从Protocol Buffer二进制序列化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转换的data,一般用来内部使用
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:

//学生模型
message student{  
    required string name = 1;   //姓名  
    required int32  age = 2;    //年龄  
    optional string addr = 3;  
}  
  
//班级模型,包含班级名和学生  
message class{  
    required string name = 1;   //班级名称  
    repeated student member = 2;    //班级成员 
}

初始化时的textFormat格式应为

name: "Communication 2004"  
member {  
  name: "flyan338"  
  age: 26  
  addr: "china"  
}  
member {  
  name: "likeliu"  
  age: 25  
  addr: "china"  
}  
member {  
  name: "gaoy"  
  age: 24  
  addr: "American"  
}  

这份配置表明:一个叫做 "Communication 2004"的班级,有3个student,你可以直接用protobuf来load出来

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342