ModelRocket 1.3

ModelRocket 1.3

测试已测试
语言语言 SwiftSwift
许可协议 MIT
发布最后发布2016 年 4 月
SPM支持 SPM

Jonathan Landon 维护。



  • 作者:
  • Jonathan Landon

ModelRocket

一个用于创建基于 JSON 的模型的 iOS 框架。用 Swift 编写(因为真的很棒!)

要求

  • iOS 8.0+
  • Xcode 7.3
  • Swift 2.2

安装

内嵌框架需要至少 iOS 8 的目标部署版本

Swift 包管理器

Swift 包管理器是苹果提供的一个依赖管理工具,目前处于早期设计和开发阶段。更多信息请查看其 GitHub 页面

您可以通过在 Package.swift 文件中将 ModelRocket 添加为依赖项来使用 Swift 包管理器安装 ModelRocket

import PackageDescription

let package = Package(
    name: "PROJECT_NAME",
    targets: [],
    dependencies: [
        .Package(url: "https://github.com/ovenbits/ModelRocket.git", versions: "1.2.3" ..< Version.max)
    ]
)

使用方法

创建自定义对象

class Vehicle: Model {
    let make  = Property<String>(key: "make")
    let model = Property<String>(key: "model", required: true)
    let year  = Property<Int>(key: "year") { year in
        if year < 2015 {
            // offer discount
        }
    }
    let color = Property<UIColor>(key: "color", defaultValue: UIColor.blackColor())
}

注意:与所有 Swift 变量一样,应始终使用 let,除非绝对需要使用 var。在 Model 对象的情况下,let 应用于所有 Property[Array|Dictionary] 属性,因为它仍然允许更改底层 value,除非您确实需要重新分配属性。

支持的类型

  • String
  • Bool
  • Int
  • UInt
  • Double
  • Float

除了上述核心类型外,ModelRocket 还支持以下几种类的序列化

  • NSDate — ISO8601 格式的字符串(2015-05-31T19:00:17.000+0000
  • UIColor —十六进制颜色字符串(#f6c500
  • NSURL —任何 URL 字符串(http://ovenbits.com
  • NSNumber —任何数字,可以用作 DoubleFloatIntUInt 的替代品

使用类型化数组创建对象

// `Model` subclasses get `fromJSON` and `toJSON` implementations on `JSONTransformable` for free,
// but explicit `JSONTransformable` conformance is still required
extension Vehicle: JSONTransformable {}

class Vehicles: Model {
    let vehicles = PropertyArray<Vehicle>(key: "vehicles")
}

PropertyArray 遵循 CollectionType,因此无需使用 .values 语法迭代值。例如

let allVehicles = Vehicles(json: <json>)

// using `.values` syntax
for vehicle in allVehicles.vehicles.values {
}

// using `CollectionType` conformance
for vehicle in allVehicles.vehicles {
}

创建使用类型字典的对象

class Car: Vehicle {
    let purchasedTrims = PropertyDictionary<Int>(key: "purchased_trims")
}

PropertyDictionary 适用于 CollectionType,因此遍历键和值时不需要使用 .values 语法。例如:

let vehicle = Vehicle(json: <json>)

// using `.values` syntax
for (key, trim) in vehicle.purchasedTrims.values {
}

// using `CollectionType` conformance
for (key, trim) in vehicle.purchasedTrims {
}

注:字典中的所有对象必须属于同一类型。如果它们不一致,应用不会崩溃,但不同类型的值将被丢弃。

初始化和自定义对象的用法

// instantiate object
let vehicle = Vehicle(json: json)

// get property type
println("Vehicle make property has type: \(vehicle.make.type)")

// get property value
if let make = vehicle.make.value {
    println("Vehicle make: \(make)")
}

模型对象也包含一个可失败初始化器,它只有在所有标记为 required = true 的属性非 nil 时才会返回初始化后的对象。

// instantiate object, only if `json` contains a value for the `make` property
if let vehicle = Vehicle(strictJSON: json) {
    // it's best to avoid implicitly unwrapped optionals, however, since `vehicle` is initialized iff `make` is non-nil, if can be force-unwrapped safely here
    println("Vehicle make: \(vehicle.make.value!)")
}
else {
    pintln("Invalid JSON")
}

自定义对象的子类化

class Car: Vehicle {
    let numberOfDoors = Property<Int>(key: "number_of_doors")
}

将自定义对象作为另一个对象的属性添加

自定义对象必须通过定义以下变量/函数来符合 JSONTransformable 协议:

  • class func fromJSON(json: JSON) -> T?
  • func toJSON() -> AnyObject
class Vehicle: Model {
    let manufacturer = Property<Manufacturer>(key: "manufacturer")
}

class Manufacturer: Model {
    let companyName = Property<String>(key: "company_name")
    let headquarters = Property<String>(key: "headquarters")
    let founded = Property<NSDate>(key: "founded")
}

extension Manufacturer: JSONTransformable {
    class func fromJSON(json: JSON) -> Manufacturer? {
        return Manufacturer(json: json)
    }
    func toJSON() -> AnyObject {
        return self.json().dictionary
    }
}

使用枚举作为属性

ModelRocket 支持 Property[Array|Dictionary] 属性的枚举类型,只要枚举符合 JSONTransformable 协议。

作为一个简单的例子,一辆车内材料类型可以使用枚举如下所示:

enum VehicleInterior: String {
    case Fabric = "fabric"
    case Leather = "leather"
}

extension VehicleInterior: JSONTransformable {
    static func fromJSON(json: JSON) -> VehicleInterior? {
        return VehicleInterior(rawValue: json.stringValue)
    }
    func toJSON() -> AnyObject {
        return rawValue
    }
}

class Vehicle: ModelRocket {
   let interior = Property<VehicleInterior>(key: "interior")
}

属性 postProcess 挂钩

Property postProcess 封闭(在 PropertyArrayPropertyDictionary 上也有效)提供在工作完成所有 Model 对象的属性从 JSON 初始化之后但在 Model 对象完成初始化之前执行机制。

class Vehicles: Model {
    let vehicles = PropertyArray<Vehicle>(key: "vehicles") { (values) -> Void in
        for vehicle in values {
            println("postHook vehicle: \(vehicle.make.value!)")
        }
    }
}

.value 绑定器使用模式

ModelRocket 属性为 Property<T> 类型。访问属性值时,您将通过 Property.value,例如:

let vehicleMake = make.value

直接利用 Property 属性值是完全可以接受的。但是,您可能希望对模型对象使用不同的公共API。

private let _make = Property<String>(key: "make")
public var make: String {
  get {
    return make.value ?? "unknown make"
  }
  set {
    make.value = newValue
  }
}

这个使用模式使您可以:

  • 一个更干净的公共API
  • 一个使类型更合适的公共API:我们期望“make”是字符串,而不是 Property
  • 由于它必须适用于一般情况,所以 value 是可选的,但您的API可能更正确地不需要可选。当然,如果您的API想要可选的,也没问题。
  • 处理或转换原始 JSON 值到更适合您对象公共 API 的其他值的能力
  • 一次可以设置,但对于只读属性,您可以选择省略设置访问器,这样就可以更准确地暴露您所希望的对象API。
  • 这种桥接模式的使用使得 ModelRocket 变得成为实现细节并最小化依赖和长期维护。

实现类簇

重写 modelForJSON(json: JSON) -> Model 函数

class Vehicle: Model {
    let make = Property<String>(key: "make")
    let model = Property<String>(key: "model")
    let year = Property<Int>(key: "year")
    let color = Property<UIColor>(key: "color")
    let manufacturer = Property<Manufacturer>(key: "manufacturer")

    override class func modelForJSON(json: JSON) -> Vehicle {

        switch json["type"].stringValue {
        case "car":
            return Car(json: json)
        case "plane":
            return Plane(json: json)
        case "bike":
            return Bike(json: json)
        default:
            return Vehicle(json: json)
        }
    }
}

然后,要访问子类特定的属性,使用 switch-case 结构

let vehicle = Vehicle.modelForJSON(vehicleJSON)

switch vehicle {
case let car as Car:
    // drive the car
case let plane as Plane:
    // fly the plane
case let bike as Bike:
    // ride the bike
default:
    // do nothing
}

获取对象的 JSON 表示形式

在 Model 子类上调用 json() 函数返回一个包含以下内容的元组:

  • 词典:[String : AnyObject]
  • json: JSON
  • 数据: NSData

获取一个自定义对象的副本

调用对象上的 copy() 方法,并将其强制转换为正确类型。示例

let vehicleCopy = vehicle.copy() as! Vehicle

授权

ModelRocket 按MIT授权发布。有关详细信息,请参阅 LICENSE。