Created
August 13, 2015 22:53
-
-
Save jkopelioff/a6100b067c96662c48f7 to your computer and use it in GitHub Desktop.
Model Factory that maps Dictionary value to Model properties
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // ModelFactory.swift | |
| // Society6 | |
| // | |
| // Created by Joel Kopelioff on 8/10/15. | |
| // Copyright (c) 2015 Demandmedia Inc. All rights reserved. | |
| // | |
| import Foundation | |
| class ModelFactory { | |
| class func createModels<Model:BaseModel> (json:[NSDictionary], error:NSErrorPointer, modelType:Model.Type? = nil) -> [Model] | |
| { | |
| var objects = [Model]() | |
| for dict in json { | |
| if let model = ModelFactory.createModel(dict, error: error, modelType:modelType) { | |
| objects.append(model) | |
| } | |
| if let error = error.memory { | |
| break; | |
| } | |
| } | |
| return objects | |
| } | |
| class func createModel<Model:BaseModel> (json:NSDictionary, error:NSErrorPointer, modelType:Model.Type? = nil) -> Model? | |
| { | |
| var object = Model() | |
| if modelType != nil { | |
| object = modelType!() | |
| } | |
| var modelAttributes = object.attributes | |
| for attributeAndTypes in modelAttributes { | |
| var set = false | |
| var attribute = attributeAndTypes.0 | |
| let type:Any.Type = attributeAndTypes.1 | |
| // Internal function to set values for mapped and non-mapped attributes | |
| func setValue(value:AnyObject?) { | |
| if value == nil { return } | |
| var convertedValue:AnyObject? | |
| // Convert types | |
| if let elementType = type as? Bool.Type where value is String { | |
| convertedValue = value?.boolValue | |
| } else if let elementType = type as? Float?.Type where value is String { | |
| convertedValue = value?.floatValue | |
| } else if let elementType = type as? Int.Type where value is String { | |
| convertedValue = value?.integerValue | |
| } else if let elementType = type as? String?.Type where value is String { | |
| convertedValue = value | |
| } else if "\(type)".match("Array") && value is Array<NSDictionary> { | |
| let matches = "\(type)".captureUsingRegex("Array<([\\w\\.]+)>") | |
| if matches.count > 0 && matches[0].count > 1 { | |
| let className = matches[0][1] | |
| let classType = NSClassFromString(className) as! BaseModel.Type | |
| let object = classType() | |
| // Special case | |
| var error:NSError? | |
| convertedValue = ModelFactory.createModels(value as! [NSDictionary], error: &error, modelType:object.dynamicType) | |
| } | |
| } else { | |
| // We don't convert this type, yet | |
| println("Attribute: \(attribute) Type: \(type) Value: \(value)") | |
| } | |
| if let valueToSet: AnyObject = convertedValue { | |
| object.setValue(valueToSet, forKey: attribute) | |
| set = true | |
| } | |
| } | |
| // First check to see if attribute maps directly | |
| if let value:AnyObject? = json.valueForKey(attribute) where value != nil { | |
| setValue(value) | |
| } | |
| // Next check if we have a mapping override | |
| if let mappings = object.mappings, | |
| let mapArray = mappings[attribute] where Set(mappings.keys.array).contains(attribute) { | |
| for map in mapArray { | |
| // Take the first attribute that matches, discard the remaining | |
| if let value:AnyObject? = json.valueForKeyPath(map) where value != nil { | |
| setValue(value) | |
| break | |
| } | |
| } | |
| } | |
| if !set { | |
| NSLog("Did not set \"\(attribute)\"") | |
| } | |
| } | |
| return object | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Called like so...