Swift下使用Protobuf

Swift下使用Protobuf

新年伊始,大家元旦快乐!

进入主题:Swift下使用Protobuf,属于扫盲贴,仅此记录过程。

对于protobuf不算太陌生但也不算非常6。之前玩cocos的时候C/S通信协议就是用的protobuf,因为是游戏对于消息的解析速度和大小要求还是比较高的,所以一般稍微大点的游戏都不会采用xml或者json这些可读性很强的序列化格式,之前有个项目组有的是amf3(不要问为啥,因为忒么人家是页游,当年AS3火的一塌糊涂),有个组是自己写二进制序列化和反序列化(默默滴说句:这种活吃力不讨好,看着他们天天对协议感觉好累)。

之后新开项目的时候我推荐大家使用protobuf,开始是在C++项目上使用,之后又在lua项目上使用,那时候用的是protobuf2.5,之后出了3.X的版本不过之后没有用到这一块所以也就不怎么了解,之后如果深入会继续记录下来学习之。

当然很感谢那些年一起的朋友们,大家新年好!

好,先装protobuf,下载链接地址:
https://github.com/google/protobuf/releases

选个版本来自己下载,下载完后解压之。进入到swift-protobuf文件夹下,非常C风格的make,依次执行如下命令:

1
2
3
4
./configure
make
make check
sudo make install

正常执行完后输入protoc –version
得到结果:libprotoc 3.5.1
我装的是3.5.1版本,so安装成功。

我们看下帮助
protoc –help
可以看到现在支持很多语言的导出:

1
2
3
4
5
6
7
8
9
--cpp_out=OUT_DIR Generate C++ header and source.
--csharp_out=OUT_DIR Generate C# source file.
--java_out=OUT_DIR Generate Java source file.
--javanano_out=OUT_DIR Generate Java Nano source file.
--js_out=OUT_DIR Generate JavaScript source.
--objc_out=OUT_DIR Generate Objective C header and source.
--php_out=OUT_DIR Generate PHP source file.
--python_out=OUT_DIR Generate Python source file.
--ruby_out=OUT_DIR Generate Ruby source file.

没有swift,但有Objective-C,but不打算通过构建bridge来互相调用,只想直接导出swift。Apple其实已经帮大家做了个很好的仓库:
https://github.com/apple/swift-protobuf

安装过程也非常简单。git clone仓库下来,cd到swift-protobuf仓库目录下执行

1
swift build -c release -Xswiftc -static-stdlib

成功之后,我们来随便写个proto文件。

1
2
3
4
5
6
7
8
9
syntax = "proto3";
package Im;
message helloworld
{
int32 id = 1; // ID
string str = 2; // str
int32 opt = 3; //optional field
}

OK,现在cd到proto文件所在文件夹,直接运行

1
protoc *.proto --swift_out=/Users/apple/Desktop

这样子在桌面就生成了一个msg.pb.swift文件,接下来xcode new a project,直接丢这个生成好的文件进工程,因为我使用的cocoapod方式来集成framwork,所以直接Podfile文件下加一句
pod ‘SwiftProtobuf’
更新完pod后直接上代码测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//
// ViewController.swift
// TestProtobuf
//
// Created by apple on 2018/1/1.
// Copyright © 2018年 apple. All rights reserved.
//
import UIKit
import SwiftProtobuf
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
testProtobuf()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func testProtobuf() -> Void {
var obj = Im_helloworld()
obj.id = 21
obj.opt = 12
obj.str = "dkdk"
do {
let protoData: Data = try obj.serializedData()
print("生成的二进制大小为:\(protoData.count) bytes")
let decodedInfo = try Im_helloworld(serializedData: protoData)
print("decodedInfo str = \(decodedInfo.str)")
print("decodedInfo opt = \(decodedInfo.opt)")
print("decodedInfo id = \(decodedInfo.id)")
} catch {
print(error)
}
}
}

获得如下输出:

生成的二进制大小为:10 bytes
decodedInfo str = dkdk
decodedInfo opt = 12
decodedInfo id = 21

坑:
对于直接丢framework到Xcode工程的童鞋,
记住千万不要直接拖到工程目录
记住千万不要直接拖到工程目录
记住千万不要直接拖到工程目录

因为你需要在General – Embedded Binaries中添加编译出的SwiftProtobuf.framework
如果,直接拖拽到工程中使用,会报错:
dyld: Library not loaded: @rpath/SwiftProtobuf.framework/SwiftProtobuf
Referenced from: /var/containers/Bundle/Application/**/ProductsName.app/ProductsName
Reason: image not found

OK,先简单这样。
之后看看golang的导出和简单使用,大概猜到我要干啥了吧~
gRPC,木有错~!!
新一年继续努力吧

参考链接:
链接:https://www.jianshu.com/p/751aa2b621d5
作者:y824165978