Protobuf
Protobuf 即 google protocol buffer 是一种数据封装格式协议,是google推出
的一种语言无关、平台无关、扩展性好的用于通信协议、数据存储的结构化数据串行化方法。支持
C++、Python、Java三种语言。
1、安装 Protobuf 工具
最简单的方式是直接通过 brew 进行安装:
brew install protobuf // 支持生成.h和.m文件,和其他多种语言的文件
brew install swift-protobuf // 支持生成.swift文件
检查是否安装成功:
protoc --version
protoc-gen-swift --version
2、创建 .proto 文件
// 使用V3语法
syntax = "proto3"
// OC语言可选,添加模型文件前缀
option objc_class_prefix = "MY"
// message代表一个模型
message Test {
string title = 1;
int32 tag = 2;
Request request = 3; // 自定义的 Request 类型
repeated string values = 4; // 数组
}
message Request {
string url = 1;
}
3、proto文件 转化成objc文件
在桌面上建立两个文件夹,一个叫protofile,一个叫objcfile
然后将创建好的person.proto放进protofile文件夹,然后
cd Desktop
在终端输入:
protoc --proto_path=protofile --objc_out=objcfile message.proto
protoc --proto_path=protofile --swift_out=objcfile message.proto
然后成功在objcfile里得到我们要的文件 这将在当前目录下生成Message.pbobjc.h和Message.pbobjc.m文件。
4、在 iOS 工程中的使用
工程添加依赖
pod 'Protobuf' // OC和其他多种语言的能力依赖
pod 'SwiftProtobuf' // swift能力依赖
将生成的.pbobjc.h和.pbobjc.m文件添加到你的Xcode项目中。
导入模型头文件
#import "Message.pbobjc.h"
导入工程中,这两个文件是采用的手动引用计数,因此在加入项目后需要设置它们的编译参数。
在工程target->Build Phrases->Compile Sources->给Person.pbobjc.m设置-fno-objc-arc.
使用生成的类构建请求并发送
在你的iOS应用中,使用这些类来构建请求并发送到服务器。这里是一个使用URLSession发送protobuf请求的示例:
#import "Message.pbobjc.h"
// 创建消息实例并填充数据
MyRequest *request = [MyRequest message];
request.name = @"John Doe";
request.id = 123;
// 将消息序列化为Data对象
NSData *data = [request data];
// 创建URLRequest并设置HTTP方法、URL和HTTPBody
NSMutableURLRequest *requestObj = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://yourserver.com/api"]];
[requestObj setHTTPMethod:@"POST"];
[requestObj setHTTPBody:data];
[requestObj setValue:@"application/x-protobuf" forHTTPHeaderField:@"Content-Type"];
// 使用URLSession发送请求
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:requestObj completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
NSLog(@"Error: %@", error);
} else {
// 处理响应数据...
NSLog(@"Response received");
}
}];
[dataTask resume];
处理服务器响应(可选)
如果服务器返回了protobuf格式的数据,你可以使用相同的方式解析这些数据:
// 假设这是从服务器接收到的数据(NSData类型)
NSData *responseData = ...; // 从服务器响应中获取的数据
MyResponse *response = [MyResponse parseFromData:responseData error:nil]; // 假设MyResponse是对应的protobuf类
if (response) {
// 处理解析后的数据...
} else {
NSLog(@"Failed to parse response");
}
`` /* { "title": "test", "tag": 1, "request": { "url": "www.fivehow.com" }, "values": ["value1", "value2"] } */
// ProtoBuf data
WHTest *test = [[WHTest alloc] init];
test.title = @"test";
test.tag = 1;
test.valuesArray = [NSMutableArray
arrayWithObjects:@"value1", @"value2", nil];
WHRequest *request = [[WHRequest alloc] init];
request.URL = @"www.fivehow.com";
test.request = request;
NSData *protoBufData = [test data];
// Json Data
NSString* jsonStr = @"{\"title\":\"test\", \"tag\":1, \"request\":{\"url\":\"www.fivehow.com\"},\"values\":[\"value1\", \"value2\"]}";
NSData* jsonData = [jsonStr dataUsingEncoding:(NSUTF8StringEncoding)];
// 对比 data length
NSLog(@"protoBufData: %ld", protoBufData.length); // 43
NSLog(@"jsonData: %ld", jsonData.length); // 92`
在iOS应用中使用protobuf来发送和接收数据。确保你的服务器端也支持protobuf,并且正确配置了相应的服务接口来处理protobuf格式的数据。
swift
跟正常使用某个类的方法一样。
/* { "title": "test", "tag": 1, "request": { "url": "www.fivehow.com" }, "values": ["value1", "value2"] } */ let request = Request.with { 0.url = "www.whlcj.github.io" } // ProtoBuf data let test = Test.with { 0.title = "test" 0.request = request $0.values = ["value1", "value2"] } let binaryData = try? test.serializedData() guard let binaryData = binaryData else { return } _ = try? Test(serializedData: binaryData) // Json Data let jsonStr = "{"title":"test", "tag":1, "request":{"url":"www.whlcj.github.io"},"values":["value1", "value2"]}"
let jsonStrData = jsonStr.data(using: .utf8)
// 对比 data length print("binaryData: (binaryData.count)") // 43
guard let jsonStrData = jsonStrData else { return } print("jsonStrData: (jsonStrData.count)") // 92
使用protobuf发起请求
请求行和请求头与普通Http请求一致
请求体可使用protobuf方式生成二进制数据,设置到请求体中
let data = try? requestMessage.serializedData() request.httpBody = data
guard let url = URL(string: "xxx.com/api/room/en…") else { return } var request = URLRequest(url: url) // 设置请求行 request.httpMethod = "POST" // 设置请求头 request.setValue("application/x-protobuf", forHTTPHeaderField: "Content-Type") // 构造请求体 let requestMessage = YCRequest.with { request in request.anchorID = 2118859354127 request.roomID = 1978193384833024376 } let data = try? requestMessage.serializedData() request.httpBody = data let task = URLSession.shared.dataTask(with: request) { data, response, error in } task.resume()
解析数据
使用protobuf 自带的数据解析,可完成 二进制数据 -> 模型数据 映射
let responseMessage = try? Room(serializedData: data) guard let responseMessage else { print("Failed to decode response.") return } print("Server response: (responseMessage)")