简介
Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。
-
官网
https://developers.google.com/protocol-buffers/
-
Github
https://github.com/google/protobuf
-
SwiftProtobuf
https://github.com/apple/swift-protobuf
-
参考网站:
4.1 数据交换利器 Protobuf 技术浅析 http://blog.jobbole.com/107405/ 4.2 swift Protobuf https://www.jianshu.com/p/89efeecd5b43 4.3 OC Protobuf https://www.jianshu.com/p/6009e96866e5 4.4 Protobuf 的 proto3 与 proto2 的区别 https://solicomo.com/network-dev/protobuf-proto3-vs-proto2.html
搭建环境
1、 首先我们需要在mac电脑上安装google的protobuf编译器
brew install protobuf
2、生成 protoc-gen-swift(如果是oc, 不需要此步骤)
google的编译器是不包含如何生存swift代码的,所以还需要安装一个用于生成swift代码的工具 protoc-gen-swift
$ git clone https://github.com/apple/swift-protobuf.git // 见图2.2.1
$ cd swift-protobuf
$ git tag -l // 该命令将展示所有的tag_name 见图2.2.2
$ git checkout tags/[tag_name] // checkout指定tag 见图2.2.2
$ swift build // build 指定代码 见图2.2.2
build 结束之后,在.build/debug目录下会生成 protoc-gen-swift 二进制文件
$ mkdir ~/bin // 生成 ~/bin目录
$ cp .build/debug/protoc-gen-swift ~/bin // 将protoc-gen-swift拷贝到~/bin目录下
$ vim ~/.bash_profile // 打开bash_profile 环境, 配置环境变量PATH
$ export PATH=/Users/yangyu/bin:$PATH // (/Users/breeze/bin是bin对应的路径, 每个电脑的情况不同, 见图2.2.3)
$ source ~/.bash_profile
$ protoc-gen-swift -v // 见图2.2.4
如果展示出版本信息,说明protoc-gen-swift配置成功;
需要注意的是版本号,如:** protoc-gen-swift 1.0.3 **,后续需要使用;
图2.2.1
图2.2.2
图2.2.3
图2.2.4
编译proto文件
1.编写proto, 具体参照官网要求
https://developers.google.com/protocol-buffers/docs/proto3
例
syntax = "proto3" //指定proto版本, 还有proto2, 不知道默认是proto2
message DBMyAlbum {
required int64 album_id = 1;
required string album_name = 2;
optional string album_display_pic = 3;
required int32 album_type = 4 [default = 0];
repeated string album_photos_local_url = 5;
enum AlbumType {
NORMAL = 0;
TRASH = 1;
ITUNES = 2;
}
}
-
编译该文件
protoc --swift_out=. Album.proto
编译失败时, 终端里会有提示对应的错误, 根据提示, 修改对应的错误.
[图片上传失败...(image-59f176-1524462266835)]
修改完成后, 代码如下, 继续编译.
syntax = "proto3";
message DBMyAlbum {
int64 album_id = 1;
string album_name = 2;
string album_display_pic = 3;
int32 album_type = 4;
repeated string album_photos_local_url = 5;
enum AlbumType {
NORMAL = 0;
TRASH = 1;
ITUNES = 2;
}
}
编译得到一个DBMyAlbum.pb.swift文件, 代码如下
// DO NOT EDIT.
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: DBMyAlbum.proto
//
// For information on using the generated types, please see the documenation:
// https://github.com/apple/swift-protobuf/
import Foundation
import SwiftProtobuf
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that your are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
struct DBMyAlbum {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
var albumID: Int64 = 0
var albumName: String = String()
var albumDisplayPic: String = String()
var albumType: Int32 = 0
var albumPhotosLocalURL: [String] = []
var unknownFields = SwiftProtobuf.UnknownStorage()
enum AlbumType: SwiftProtobuf.Enum {
typealias RawValue = Int
case normal // = 0
case trash // = 1
case itunes // = 2
case UNRECOGNIZED(Int)
init() {
self = .normal
}
init?(rawValue: Int) {
switch rawValue {
case 0: self = .normal
case 1: self = .trash
case 2: self = .itunes
default: self = .UNRECOGNIZED(rawValue)
}
}
var rawValue: Int {
switch self {
case .normal: return 0
case .trash: return 1
case .itunes: return 2
case .UNRECOGNIZED(let i): return i
}
}
}
init() {}
}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
extension DBMyAlbum: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = "DBMyAlbum"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "album_id"),
2: .standard(proto: "album_name"),
3: .standard(proto: "album_display_pic"),
4: .standard(proto: "album_type"),
5: .standard(proto: "album_photos_local_url"),
]
mutating func decodeMessage(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
switch fieldNumber {
case 1: try decoder.decodeSingularInt64Field(value: &self.albumID)
case 2: try decoder.decodeSingularStringField(value: &self.albumName)
case 3: try decoder.decodeSingularStringField(value: &self.albumDisplayPic)
case 4: try decoder.decodeSingularInt32Field(value: &self.albumType)
case 5: try decoder.decodeRepeatedStringField(value: &self.albumPhotosLocalURL)
default: break
}
}
}
func traverse(visitor: inout V) throws {
if self.albumID != 0 {
try visitor.visitSingularInt64Field(value: self.albumID, fieldNumber: 1)
}
if !self.albumName.isEmpty {
try visitor.visitSingularStringField(value: self.albumName, fieldNumber: 2)
}
if !self.albumDisplayPic.isEmpty {
try visitor.visitSingularStringField(value: self.albumDisplayPic, fieldNumber: 3)
}
if self.albumType != 0 {
try visitor.visitSingularInt32Field(value: self.albumType, fieldNumber: 4)
}
if !self.albumPhotosLocalURL.isEmpty {
try visitor.visitRepeatedStringField(value: self.albumPhotosLocalURL, fieldNumber: 5)
}
try unknownFields.traverse(visitor: &visitor)
}
func _protobuf_generated_isEqualTo(other: DBMyAlbum) -> Bool {
if self.albumID != other.albumID {return false}
if self.albumName != other.albumName {return false}
if self.albumDisplayPic != other.albumDisplayPic {return false}
if self.albumType != other.albumType {return false}
if self.albumPhotosLocalURL != other.albumPhotosLocalURL {return false}
if unknownFields != other.unknownFields {return false}
return true
}
}
extension DBMyAlbum.AlbumType: SwiftProtobuf._ProtoNameProviding {
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
0: .same(proto: "NORMAL"),
1: .same(proto: "TRASH"),
2: .same(proto: "ITUNES"),
]
}
注意点: _ 的书写方式在编译后变成了驼峰.
在项目中使用protobuf
把编译的 DBMyAlbum.pb.swift 文件, 导入到项目中.
-
导入SwiftProtobuf, 版本号需和protoc-gen-swift -v里面的版本号一致
pod 'SwiftProtobuf', '~> 1.0.3'
-
使用
var album = DBMyAlbum() album.albumID = 1; album.albumName = "Live Photo" album.albumDisplayPic = "displayPic"![[email protected]](https://upload-images.jianshu.io/upload_images/1792156-1e32b64f9f0f43df.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) album.albumType = Int32(DBMyAlbum.AlbumType.normal.rawValue) album.albumPhotosLocalURL .append("/tmp/abc.png") guard let data = try? album.serializedData() else { return } print("-------data------") print(data) guard let jsonData = try? album.jsonUTF8Data() else { return } print("-------jsonData------") print(jsonData) guard let album2 = try? DBMyAlbum(serializedData: data) else { return } print("-------album2------") print(album2.albumID) print(album2.albumDisplayPic)