Created
May 11, 2018 09:46
-
-
Save Akhu/5ea1ecbd652fb269f7c4e7db27bc79cc to your computer and use it in GitHub Desktop.
Mixing Codable and Core Data in Swift
This file contains 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
// | |
// Article.swift | |
// Veille | |
// | |
// Created by Anthony Da Cruz on 26/01/2018. | |
// Copyright © 2018 Anthony Da Cruz. All rights reserved. | |
// | |
import Foundation | |
import CoreData | |
class Article: NSManagedObject, Decodable { | |
@NSManaged var title:String! | |
@NSManaged var summary:String? | |
@NSManaged var link:URL! | |
@NSManaged var image:URL? | |
@NSManaged var createdDate: Date | |
//var tags:[String]? | |
@NSManaged var id:UUID | |
enum CodingKeys: String, CodingKey { | |
case title | |
case summary = "description" | |
case link | |
case image = "imageURL" | |
case createdDate = "date" | |
} | |
required convenience init(from decoder: Decoder) throws { | |
guard let contextUserInfoKey = CodingUserInfoKey.context else { fatalError("cannot find context key") } | |
guard let managedObjectContext = decoder.userInfo[contextUserInfoKey] as? NSManagedObjectContext else { fatalError("cannot Retrieve context") } | |
guard let entity = NSEntityDescription.entity(forEntityName: "Article", in: managedObjectContext) else { fatalError() } | |
self.init(entity: entity, insertInto: nil) | |
let values = try decoder.container(keyedBy: CodingKeys.self) | |
self.createdDate = Date() | |
self.title = try values.decode(String.self, forKey: .title) | |
self.summary = try values.decode(String.self, forKey: .summary) | |
guard let linkString = try values.decodeIfPresent(String.self, forKey: .link) else { return } | |
if let linkUrl = URL(string: linkString) { | |
self.link = linkUrl | |
} | |
if let imageURLString = try values.decodeIfPresent(String.self, forKey: .image) { | |
if let imageURL = URL(string: imageURLString){ | |
self.image = imageURL | |
} | |
} | |
} | |
} | |
extension Article: Encodable{ | |
public func encode(to encoder: Encoder) throws { | |
var container = encoder.container(keyedBy: CodingKeys.self) | |
try container.encode(self.title, forKey: .title) | |
try container.encodeIfPresent(self.summary, forKey: .summary) | |
try container.encodeIfPresent(self.image, forKey: .image) | |
try container.encode(self.link, forKey: .link) | |
try container.encode(self.createdDate.toIso8601(), forKey: .createdDate) | |
} | |
} | |
extension CodingUserInfoKey { | |
static let context = CodingUserInfoKey(rawValue: "context") | |
} | |
// Use it : | |
let context = CoreDataStack.store.persistentContainer.newBackgroundContext() //Getting context | |
let plistDecoderForArticle = PropertyListDecoder() | |
plistDecoderForArticle.userInfo[CodingUserInfoKey.context!] = context //Pass it to CodingUserInfoKey which is made for that | |
let decodedData = try plistDecoderForArticle.decode([Article].self, from: data) //Decoding init got the managedObjectContext | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
No. I did not. For a production code I would split into three models DTO and DAO and actual model used elsewhere expect decoding a stream from the Internet and CoreData. For ex.