Skip to content

Instantly share code, notes, and snippets.

@sambhav7890
Created November 27, 2017 13:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sambhav7890/3e8306099c242b31555a8f96e2275549 to your computer and use it in GitHub Desktop.
Save sambhav7890/3e8306099c242b31555a8f96e2275549 to your computer and use it in GitHub Desktop.
Codable Compatibility for NSManagedObjects
/*
//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
}
}
}
}
@zakkhoyt
Copy link

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 {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment