Server-Driven CALayer
- CALayer
- CAShapeLayer
- CATextLayer
- CAScrollLayer
- CAGradientLayer
- CAReplicatorLayer
let json: String = ""
let model = SDCALayer.load(fromJSON: json)
let layer: CALayer = model?.convertToLayer()
let model = SDCALayer.load(fromYAML: yaml)
let layer = CAShapeLayer()
/* ~ customize layer ~ */
let model = SDCALayer(model: layer.codable())
let json: String = model?.json
let yaml: String = model?.yaml
Layer's models are defined in the following directory. Models
{
"frame": [
[
0,
0
],
[
100,
50
]
],
"cornerRadius": 5.0,
"borderColor": {
"code": "#FF0088"
},
// other properties
}
Since we need to know the actual class of the Layer, we need to receive a model with the class name and a model for each class, as follows
{
"class": "CAShapeLayer",
"layerModel": {
// CAShapeLayer Model
}
}
By using the p-x9/IndirectlyCodable library, CALayer indirectly conforms to the Codable
protocol, allowing inter-conversion with json.
Suppose we have the following customized layer class.
class AALayer: CALayer {
var newProperty: String? = "AAAA"
}
create layer model like this.
click to expand
class JAALayer: JCALayer {
typealias Target = AALayer // alias for target layer class
// Coding key (codable)
private enum CodingKeys: String, CodingKey {
case newProperty
}
// Target class name to exact layer class
// You must specify the class name including the product name and package name.
// (ex. MyApp.AALayer)
public override class var targetTypeName: String {
String(reflecting: Target.self)
}
override init() {
super.init()
}
// Decodable
public required init(from decoder: Decoder) throws {
try super.init(from: decoder)
let container = try decoder.container(keyedBy: CodingKeys.self)
newProperty = try container.decodeIfPresent(String.self, forKey: .newProperty)
}
public required convenience init(with object: CALayer) {
self.init()
reverseApplyProperties(with: object)
}
// Encodable
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(newProperty, forKey: .newProperty)
}
// apply properties to taget from model
// model -> target
public override func applyProperties(to target: CALayer) {
super.applyProperties(to: target)
guard let target = target as? AALayer else { return }
target.newProperty = newProperty
}
// apply properties to model from target
// targe -> model
public override func applyProperties(with target: CALayer) {
super.applyProperties(with: target)
guard let target = target as? AALayer else { return }
newProperty = target.newProperty
}
public override func convertToLayer() -> CALayer? {
let layer = AALayer()
self.applyProperties(to: layer)
return layer
}
}
Finally, specify the model class in the layer class extension
extension AALayer {
public typealias Target = JAALayer
public override class var codableTypeName: String {
String(reflecting: Target.self)
}
}
Start the server, change the json, save it, and it will be reflected in the app. install calayer-ws app to yor iphone (or simulator) and connect your server.
A | B |
---|---|
python ./server/ws-hotreload-server.py "<path to json>"
example json file is here.
python ./server/ws-hotreload-server.py "./Example/json/star.json"