Created
November 27, 2017 13:04
-
-
Save sambhav7890/3e8306099c242b31555a8f96e2275549 to your computer and use it in GitHub Desktop.
Codable Compatibility for NSManagedObjects
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
/* | |
//Extended Protocol which allows decoding NSManagedObjects using swift4 Codable Protocol. | |
//Requires the convenience initializer implementation as follows | |
public final class City: NSManagedObject, ManagedObjectCodable { | |
convenience public init(from decoder: Decoder) throws { | |
// Get Context from decoder | |
guard let context = decoder.userInfo[.context] as? NSManagedObjectContext else { fatalError("No Managed Object Context!") } | |
// Get Entity from Self-class-name | |
guard let entity = NSEntityDescription.entity(forEntityName: String(describing:type(of: self)), in: context) else { fatalError("No Managed Entity Description!") } | |
// Default init for NSManagedObjects | |
self.init(entity: entity, insertInto: context) | |
// Protocol Method to parse data | |
try self.loadData(from: decoder, keyType: CityCodingKeys.self) | |
// performing any property manipulations if required | |
if self.populationRanking < 1 { self.populationRanking = Int16.max } | |
// State is an NSManagedObject relationship | |
self.state = try decoder.container(keyedBy: CityCodingKeys.self).decode(State.self, forKey: Cities.CityCodingKeys.state) | |
} | |
// And the City class would have an CodingKey compliant enumeration | |
enum CityCodingKeys: String, CodingKey { | |
case state | |
case name | |
case modifiedAt = "modified_at" | |
case ranking | |
case id | |
} | |
} | |
//Usage >> | |
let decoder = JSONDecoder() | |
decoder.userInfo[.context] = <NSManagedObjectContext> | |
let parsedValue = try decoder.decode(City.self, from: cityResponseData) | |
*/ | |
import Foundation | |
import CoreData | |
public extension CodingUserInfoKey { | |
public static let context = CodingUserInfoKey(rawValue: "context")! | |
} | |
public protocol ManagedCodableProtocol: Codable { } | |
public extension ManagedCodableProtocol where Self: NSManagedObject { | |
func loadData<Key>(from decoder: Decoder, keyType: Key.Type) throws where Key: CodingKey { | |
let container = try decoder.container(keyedBy: Key.self) | |
let attributes = self.entity.attributesByName | |
for nameKey in container.allKeys { | |
guard let subStrName = "\(nameKey)".split(separator: ".").last else { continue } | |
let name = String(subStrName) | |
guard let attr = attributes[name] else { continue } | |
let attrType = attr.attributeType // NSAttributeType enumeration for the property type | |
switch attrType { | |
case .integer16AttributeType: | |
let value = try container.decodeIfPresent(Int16.self, forKey: nameKey) | |
self.setValue(value, forKey: name) | |
case .integer32AttributeType: | |
let value = try container.decodeIfPresent(Int32.self, forKey: nameKey) | |
self.setValue(value, forKey: name) | |
case .integer64AttributeType: | |
let value = try container.decodeIfPresent(Int64.self, forKey: nameKey) | |
self.setValue(value, forKey: name) | |
case .decimalAttributeType: | |
let value = try container.decodeIfPresent(Decimal.self, forKey: nameKey) | |
self.setValue(value, forKey: name) | |
case .doubleAttributeType: | |
let value = try container.decodeIfPresent(Double.self, forKey: nameKey) | |
self.setValue(value, forKey: name) | |
case .floatAttributeType: | |
let value = try container.decodeIfPresent(Float.self, forKey: nameKey) | |
self.setValue(value, forKey: name) | |
case .stringAttributeType: | |
let value = try container.decodeIfPresent(String.self, forKey: nameKey) | |
self.setValue(value, forKey: name) | |
case .booleanAttributeType: | |
let value = try container.decodeIfPresent(Bool.self, forKey: nameKey) | |
self.setValue(value, forKey: name) | |
case .dateAttributeType: | |
let value = try container.decodeIfPresent(Date.self, forKey: nameKey) | |
self.setValue(value, forKey: name) | |
default: | |
print("Undefined NameKey : \(nameKey)") | |
break | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think you've got a typo at link 6. Looks like you might have renamed your protocol.
Should be
public final class City: NSManagedObject, ManagedCodableProtocol {