美文网首页
iOS 的 Protocol Buffer 简单使用

iOS 的 Protocol Buffer 简单使用

作者: kwdx | 来源:发表于2019-02-22 10:37 被阅读0次

    简介

    Protocol buffers are Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data – think XML, but smaller, faster, and simpler. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages.

    简单来说,Protocol Buffers 是一种和语言平台都没关的数据交换格式。

    安装

    Mac 安装

    1. 安装 protobuf 编译所需工具

      $ brew install automake
      $ brew install libtool
      
    2. 从 git 上拉取 protobuf 源码,并生成配置脚本

      $ git clone https://github.com/protocolbuffers/protobuf.git
      $ cd protobuf
      $ git submodule update --init --recursive
      $ ./autogen.sh
      
    3. 构建安装 protobuf 编译器

      $ ./configure
      $ make
      $ make check
      $ sudo make install
      

    通过源码安装 protobuf 比较繁琐,也可以通过 brew 安装:

    brew install protobuf
    
    // Swift 版本需额外再安装swift-protoc
    brew install swift-protobuf
    

    Tips: 通过源码编译安装的路径一定不要有空格

    iOS 安装

    直接使用 pod 导入就行了:

    pod 'Protobuf'
    

    使用

    1.创建.proto文件

    proto3 语法可参考官方文档

    创建一个 SimpleMessage.proto 文件,输入以下内容

    syntax = "proto3";
    package com.protobuf;
    option objc_class_prefix = "Foo";
    
    message SimpleMessage {
        int32 msgId = 1;
        string msgContent = 2;
    }
    

    在 Objective-C 中,是没有命名空间的概念,因此 package 是没什么效果的,但在 Swift 中则是有命名空间的概念。因此在 Objective-C 语言中,可通过 objc_class_prefix 来设置类名的前缀,而在 Swift 中,则是通过 package 来设置类名前缀

    2.生成对应的iOS文件

    在命令行终端中,使用我们刚刚安装的 protoc 命令编译我们编写的 proto 文件

    // Objective-C
    protoc SimpleMessage.proto --objc_out="./"
    
    // Swift
    protoc SimpleMessage.proto --swift_out="./"
    

    网上的都说 protobuf 为了性能考虑,采用的是 MRC 模式,因此项目是使用 ARC 的话,则需要在 Compile Sources 中添加 -fno-objc-arc,但笔者不添加 -fno-objc-arc 也能正常运行。

    3.使用

    导入第二步生成的 SimpleMessage.pbobjc.hSimpleMessage.pbobjc.m 文件,FooSimpleMessage 继承 GPBMessage 类,我们可以像正常的 OC 对象一样使用它:

    FooSimpleMessage *msg = [[FooSimpleMessage alloc] init];
    msg.msgId = 1;
    msg.msgContent = @"A protobuf message content";
    NSLog(@"%@", msg);
    NSData *data = msg.data;
    NSError *error;
    FooSimpleMessage *decodeMsg = [FooSimpleMessage parseFromData:data error:&error];
    if (!error) {
        NSLog(@"%@", decodeMsg);
    }
    

    打印结果为:


    打印结果.png

    4.与服务器通信

    与服务器的通信直接传递 Protobuf 序列化后的Data即可,客户端收到服务器返回的 Protobuf 序列后的Data,直接使用 parseFromData:error: 方法转换成对应的对象即可。

    注意:服务端和客户端最好使用同一个版本的 .proto 文件生成的文件来进行序列化和反序列化

    5.其他

    在使用 Protobuf 序列化对象的时候,有两个方式序列化成数据流:msg.datamsg.delimitedData,通过 delimitedData 序列化后的数据流前面添加整体数据流的长度(不包括自己),因此👆的反序列方法是会出错的,应该用👇的方法反序列化:

    NSData *delimitedData = msg.delimitedData;
    GPBCodedInputStream *inputStream = [GPBCodedInputStream streamWithData:delimitedData];
    FooSimpleMessage *decodeMsg = [FooSimpleMessage parseDelimitedFromCodedInputStream:inputStream extensionRegistry:nil error:&error];
    

    客户端要和服务端协商统一是用 data 还是 delimitedData


    以上就是关于 Protobuf 的简单使用了,GitHub Demo

    跳下一篇 Protobuf 数据格式

    相关文章

      网友评论

          本文标题:iOS 的 Protocol Buffer 简单使用

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