美文网首页#iOS#HeminWoniOS Developer程序员
iOS引入google ProtocolBuffer(proto

iOS引入google ProtocolBuffer(proto

作者: 苹果API搬运工 | 来源:发表于2017-05-15 11:31 被阅读178次
    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出来

    相关文章

      网友评论

        本文标题:iOS引入google ProtocolBuffer(proto

        本文链接:https://www.haomeiwen.com/subject/mmthxxtx.html