ProtocolBuffers Swift Realm
Swift 中 Realm 数据模型的 Protocol Buffers 实现。
Protocol Buffers 是一种以高效且可扩展的格式编码结构化数据的方式。本项目的实现基于 Google 的 Protocol Buffers 实现。有关更多信息,请参阅 Google protobuf 项目。
Protobuf Swift Realm 编译器
所需目录
如何安装
Cocoapods
use_frameworks!
pod 'ProtocolBuffers-Swift-Realm'
.proto 文件编译
protoc -I <FILENAME>.proto --swift_realm_out="./<OUT_DIR>"
使用方法
开始使用
首先,为了使用自定义选项,需要在.proto文件中导入 swift-descriptor
import 'google/protobuf/swift-descriptor.proto';
然后,需要添加一个自定义选项来生成 Realm Data Model Swift 类
option (.google.protobuf.swift_message_options) = { generate_realm_object : true};
示例
Employee.proto
将生成到 Example.Employee.realm.swift
syntax = "proto2";
import "google/protobuf/swift-descriptor.proto";
package Example;
message Employee {
option (.google.protobuf.swift_message_options) = { generate_realm_object : true };
required string firstName = 1;
required string lastName = 2;
required double rank = 3;
optional int32 level = 4;
}
生成的 Swift Realm 数据模型对象
public class Example_Employee:Object {
@objc dynamic var firstName:String = ""
@objc dynamic var lastName:String = ""
@objc dynamic var rank:Double = 0.0
let level:RealmOptional<Int> = RealmOptional<Int>()
}
extension Example_Employee:ProtoRealm {
public typealias PBType = Example.Employee
public typealias RMObject = Example_Employee
public typealias RepresentationType = Dictionary<String,Any>
public static func map(_ proto: Example.Employee) -> Example_Employee {
let rmModel = Example_Employee()
rmModel.firstName = proto.firstName
rmModel.lastName = proto.lastName
rmModel.rank = proto.rank
if proto.hasLevel {
rmModel.level.value = Int(proto.level)
} else {
rmModel.level.value = nil
}
return rmModel
}
public func protobuf() throws -> Example.Employee {
let proto = Example.Employee.Builder()
proto.firstName = self.firstName
proto.lastName = self.lastName
proto.rank = self.rank
if let valueLevel = self.level.value {
proto.level = Int32(valueLevel)
}
return try proto.build()
}
}
主键
Protobuf Swift Realm 编译器支持两种生成 主键 的方法
添加一个支持类型的字段(string
或 int
)并命名为 "id",这将自动转换为主键
message Employee {
option (.google.protobuf.swift_message_options) = { generate_realm_object : true };
required string id = 1;
required string firstName = 2;
required string lastName = 3;
}
或者,您可以手动为必要字段设置自定义选项
message Employee {
option (.google.protobuf.swift_message_options) = { generate_realm_object : true };
required string key = 1 [(.google.protobuf.swift_field_options).realm_primary_key = true];
required string firstName = 2;
required string lastName = 3;
}
这将会生成
public class Example_Employee:Object {
@objc dynamic var key:String = ""
@objc dynamic var firstName:String = ""
@objc dynamic var lastName:String = ""
public override class func indexedProperties() -> [String] {
return ["key"]
}
public override class func primaryKey() -> String? {
return "key"
}
}
extension Example_Employee:ProtoRealm {
public typealias PBType = Example.Employee
public typealias RMObject = Example_Employee
public typealias RepresentationType = Dictionary<String,Any>
public static func map(_ proto: Example.Employee) -> Example_Employee {
let rmModel = Example_Employee()
rmModel.key = proto.key
rmModel.firstName = proto.firstName
rmModel.lastName = proto.lastName
return rmModel
}
public func protobuf() throws -> Example.Employee {
let proto = Example.Employee.Builder()
proto.key = self.key
proto.firstName = self.firstName
proto.lastName = self.lastName
return try proto.build()
}
}
索引属性
使用自定义选项来 索引 一个属性
option (.google.protobuf.swift_field_options).realm_indexed_propertie = true;
示例
message Employee {
option (.google.protobuf.swift_message_options) = { generate_realm_object : true };
required string id = 1 [(.google.protobuf.swift_field_options).realm_indexed_propertie = true];
required string firstName = 2;
required string lastName = 3;
}
这将会生成
public class Example_Employee:Object {
@objc dynamic var id:String = ""
@objc dynamic var firstName:String = ""
@objc dynamic var lastName:String = ""
public override class func indexedProperties() -> [String] {
return ["id"]
}
public override class func primaryKey() -> String? {
return "id"
}
}
extension Example_Employee:ProtoRealm {
public typealias PBType = Example.Employee
public typealias RMObject = Example_Employee
public typealias RepresentationType = Dictionary<String,Any>
public static func map(_ proto: Example.Employee) -> Example_Employee {
let rmModel = Example_Employee()
rmModel.id = proto.id
rmModel.firstName = proto.firstName
rmModel.lastName = proto.lastName
return rmModel
}
public func protobuf() throws -> Example.Employee {
let proto = Example.Employee.Builder()
proto.id = self.id
proto.firstName = self.firstName
proto.lastName = self.lastName
return try proto.build()
}
}
链接对象
要在一个对象及其所属模型对象之间创建一个关系,您需要添加一个自定义选项
option (.google.protobuf.swift_message_options) = {
linkedObjects : [{
fieldName : "department"
fromType : "Department"
propertyName : "employees"
packageName : "Example"
}]
};
- fieldName:所属对象中的字段名
- fromType:所属对象类的名称
- propertyName:所属对象中的字段名
- packageName:您的protobuf包的名称
示例
syntax = "proto2";
import "google/protobuf/swift-descriptor.proto";
package Example;
message Employee {
option (.google.protobuf.swift_message_options) = {
generate_realm_object : true
linkedObjects : [{
fieldName : "department"
fromType : "Department"
propertyName : "employees"
packageName : "Example"
}]
};
required string id = 1;
required string firstName = 2;
required string lastName = 3;
}
message Department {
option (.google.protobuf.swift_message_options) = { generate_realm_object : true};
required string id = 1;
required string name = 2;
repeated Employee employees = 3;
}
这将会生成
public class Example_Employee:Object {
@objc dynamic var id:String = ""
@objc dynamic var firstName:String = ""
@objc dynamic var lastName:String = ""
let department = LinkingObjects(fromType: Department.self, property:"employees")
public override class func indexedProperties() -> [String] {
return ["id"]
}
public override class func primaryKey() -> String? {
return "id"
}
}
public class Example_Department:Object {
@objc dynamic var id:String = ""
@objc dynamic var name:String = ""
let employees:List<Example_Employee> = List<Example_Employee>()
public override class func indexedProperties() -> [String] {
return ["id"]
}
public override class func primaryKey() -> String? {
return "id"
}
}
extension Example_Employee:ProtoRealm {
public typealias PBType = Example.Employee
public typealias RMObject = Example_Employee
public typealias RepresentationType = Dictionary<String,Any>
public static func map(_ proto: Example.Employee) -> Example_Employee {
let rmModel = Example_Employee()
rmModel.id = proto.id
rmModel.firstName = proto.firstName
rmModel.lastName = proto.lastName
return rmModel
}
public func protobuf() throws -> Example.Employee {
let proto = Example.Employee.Builder()
proto.id = self.id
proto.firstName = self.firstName
proto.lastName = self.lastName
return try proto.build()
}
}
extension Example_Department:ProtoRealm {
public typealias PBType = Example.Department
public typealias RMObject = Example_Department
public typealias RepresentationType = Dictionary<String,Any>
public static func map(_ proto: Example.Department) -> Example_Department {
let rmModel = Example_Department()
rmModel.id = proto.id
rmModel.name = proto.name
rmModel.employees.append(objectsIn:Example_Employee.map(proto.employees))
return rmModel
}
public func protobuf() throws -> Example.Department {
let proto = Example.Department.Builder()
proto.id = self.id
proto.name = self.name
proto.employees += try self.employees.map({ value in
return try value.protobuf()
})
return try proto.build()
}
}
枚举
实际上,Realm不支持枚举,但我们支持!
要处理枚举,请添加一个自定义选项
option (.google.protobuf.swift_enum_options) = { generate_realm_object : true};
示例
enum DepartmentType {
option (.google.protobuf.swift_enum_options) = { generate_realm_object : true };
DELIVERY = 0;
MANAGEMENT = 1;
SUPPORT = 2;
}
这将会生成
public class Example_DepartmentType:Object {
@objc dynamic var rawValue:String = ""
public override class func primaryKey() -> String? {
return "rawValue"
}
public override class func indexedProperties() -> [String] {
return ["rawValue"]
}
}
extension Example_DepartmentType:ProtoRealm {
public typealias PBType = Example.DepartmentType
public typealias RMObject = Example_DepartmentType
public typealias RepresentationType = String
public static func map(_ proto: Example.DepartmentType) -> Example_DepartmentType {
let rmModel = Example_DepartmentType()
rmModel.rawValue = proto.toString()
return rmModel
}
public func protobuf() throws -> Example.DepartmentType {
return try Example.DepartmentType.fromString(self.rawValue)
}
}
致谢
开发者 - Alexey Khokhlov
Google Protocol Buffers - Cyrus Najmabadi, Sergey Martynov, Kenton Varda, Sanjay Ghemawat, Jeff Dean, 和其他