ProtocolBuffers-Swift-Realm 0.4.2

ProtocolBuffers-Swift-Realm 0.4.2

Alexey Khokhlov 维护。



 
依赖项
ProtocolBuffers-Swift>= 0
RealmSwift>= 0
 

  • 作者
  • Alexey Khokhlov

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 文件编译

所需的 Protobuf Swift Realm 编译器

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 编译器支持两种生成 主键 的方法

添加一个支持类型的字段(stringint)并命名为 "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, 和其他