一个用于创建基于 JSON 的模型的 iOS 框架。用 Swift 编写(因为真的很棒!)
内嵌框架需要至少 iOS 8 的目标部署版本
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
—任何数字,可以用作 Double
、Float
、Int
和 UInt
的替代品// `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 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
封闭(在 PropertyArray
和 PropertyDictionary
上也有效)提供在工作完成所有 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
}
}
这个使用模式使您可以:
Property
value
是可选的,但您的API可能更正确地不需要可选。当然,如果您的API想要可选的,也没问题。重写 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
}
在 Model 子类上调用 json()
函数返回一个包含以下内容的元组:
词典:[String : AnyObject]
json: JSON
数据: NSData
调用对象上的 copy()
方法,并将其强制转换为正确类型。示例
let vehicleCopy = vehicle.copy() as! Vehicle
ModelRocket 按MIT授权发布。有关详细信息,请参阅 LICENSE。