Hello everyone (sorry for my bad english, I'm French),
I'm trying to put my NSManagedObject
into NSUserDefaults
to retrieve it with its relationships. Basically I used NSCoding
and I had implemented the required method, but because it's NSManaged
objects, the signature of the init method it's : init(entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext?).
The message is "'NSInvalidArgumentException', reason: 'Illegal attempt to establish a relationship 'shop' between objects in different contexts"
If I comment the line in Address : self.shop = shop
, it's creating me my entity again and again..
This is my code :
To put the shop in NSUserDefaults
:
let selectedShop = shopFetchedResultsController!.fetchedObjects![indexPath.row] as! Shop
let encodedShop = NSKeyedArchiver.archivedDataWithRootObject(selectedShop)
NSUserDefaults.standardUserDefaults().setObject(encodedShop, forKey: "currentShop")
And to retrieve it :
let encodedShop = NSUserDefaults.standardUserDefaults().objectForKey("currentShop") as! NSData
let currentShop = NSKeyedUnarchiver.unarchiveObjectWithData(encodedShop) as! Shop
Shop Entity :
import Foundation
import CoreData
@objc(Shop)
class Shop: NSManagedObject, NSCoding {
@NSManaged var name: String
@NSManaged var phoneNumber: String
@NSManaged var address: Address
@NSManaged var products: NSSet
// MARK: - Managed Object Context Insertable
class var entityName: String {
return "Shop"
}
struct Attributes {
static let Name = "name"
static let PhoneNumber = "phoneNumber"
static let Address = "address"
static let Products = "products"
}
override init(entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext?) {
super.init(entity: entity, insertIntoManagedObjectContext: context)
}
convenience init(name:String, phoneNumber:String, address:Address, products:NSSet) {
self.init(entity: NSEntityDescription.entityForName("Shop", inManagedObjectContext: ManagedObjectContext.defaultContext)!, insertIntoManagedObjectContext: ManagedObjectContext.defaultContext)
self.name = name
self.phoneNumber = phoneNumber
self.address = address
self.products = products
}
required convenience init(coder aDecoder: NSCoder) {
let name = aDecoder.decodeObjectForKey("name") as! String
let phoneNumber = aDecoder.decodeObjectForKey("phoneNumber") as! String
let address = aDecoder.decodeObjectForKey("address") as! Address
let products = aDecoder.decodeObjectForKey("products") as! NSSet
self.init(name: name, phoneNumber: phoneNumber, address: address, products: products)
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(name, forKey: "name")
aCoder.encodeObject(phoneNumber, forKey: "phoneNumber")
aCoder.encodeObject(address, forKey: "address")
aCoder.encodeObject(products, forKey: "products")
}
Address Entity :
class Address: NSManagedObject, NSCoding {
@NSManaged var city: String
@NSManaged var country: String
@NSManaged var ext: String?
@NSManaged var number: NSNumber?
@NSManaged var postalCode: String
@NSManaged var street: String
@NSManaged var customers: NSSet
@NSManaged var shop: Shop
// MARK: - Managed Object Context Insertable
class var entityName: String {
return "Address"
}
struct Attributes {
static let City = "city"
static let Country = "country"
static let Ext = "ext"
static let Number = "number"
static let PostalCode = "postalCode"
static let Street = "street"
static let Customers = "customers"
static let Shop = "shop"
}
override init(entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext?) {
super.init(entity: entity, insertIntoManagedObjectContext: context)
}
convenience init(city:String, country:String, ext:String?, number:NSNumber?, postalCode:String, street:String, customers: NSSet, shop: Shop) {
self.init(entity: NSEntityDescription.entityForName(Address.entityName, inManagedObjectContext: ManagedObjectContext.defaultContext)!, insertIntoManagedObjectContext: ManagedObjectContext.defaultContext)
self.city = city
self.country = country
self.ext = ext
self.number = number
self.postalCode = postalCode
self.street = street
self.customers = customers
// self.shop = shop
}
required convenience init(coder aDecoder: NSCoder) {
let city = aDecoder.decodeObjectForKey("city") as! String
let country = aDecoder.decodeObjectForKey("country") as! String
let ext : String? = aDecoder.decodeObjectForKey("ext") as? String
let number : NSNumber? = aDecoder.decodeObjectForKey("number") as? NSNumber
let postalCode = aDecoder.decodeObjectForKey("postalCode") as! String
let street = aDecoder.decodeObjectForKey("street") as! String
let customers = aDecoder.decodeObjectForKey("customers") as! NSSet
let shop = aDecoder.decodeObjectForKey("shop") as! Shop
self.init(city: city, country: country, ext: ext, number: number, postalCode: postalCode, street: street, customers: customers, shop: shop)
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(city, forKey: "city")
aCoder.encodeObject(country, forKey: "country")
aCoder.encodeObject(ext, forKey: "ext")
aCoder.encodeObject(number, forKey: "number")
aCoder.encodeObject(postalCode, forKey: "postalCode")
aCoder.encodeObject(street, forKey: "street")
aCoder.encodeObject(customers, forKey: "customers")
aCoder.encodeObject(shop, forKey: "shop")
}
I don't even know if it's the correct way to implement my entities..
For information, I use Swift2 and Xcode7. If you need more details, just tell me, I can provide you other things !
Thank you a lot for your help ! Trust me, I spend 3 days on that without solutions...