问题
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...
回答1:
You never do this. Core data objects are meant to be saved in DB only. However, you can use NSUserDefaults
to save any key which you can later retrieve and use to fetch data from core data.
来源:https://stackoverflow.com/questions/32709029/saving-nsmanagedobject-in-nsuserdefaults