在 NSUserDefaults 中保存 NSManagedObject

Saving NSManagedObject in NSUserDefaults

大家好(抱歉我英语不好,我是法国人),

我正在尝试将我的 NSManagedObject 放入 NSUserDefaults 以检索它及其关系。基本上我使用 NSCoding 并且我已经实现了所需的方法,但是因为它是 NSManaged 对象,init 方法的签名是:init(entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext?)。

The message is "'NSInvalidArgumentException', reason: 'Illegal attempt to establish a relationship 'shop' between objects in different contexts"

如果我评论地址中的行:self.shop = shop,它会一次又一次地创建我的实体..

这是我的代码:

将商店放在 NSUserDefaults :

let selectedShop = shopFetchedResultsController!.fetchedObjects![indexPath.row] as! Shop
let encodedShop = NSKeyedArchiver.archivedDataWithRootObject(selectedShop)
NSUserDefaults.standardUserDefaults().setObject(encodedShop, forKey: "currentShop")

并检索它:

let encodedShop = NSUserDefaults.standardUserDefaults().objectForKey("currentShop") as! NSData
let currentShop = NSKeyedUnarchiver.unarchiveObjectWithData(encodedShop) as! Shop

商店实体:

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")
}

地址实体:

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")
}

我什至不知道这是否是实现我的实体的正确方法..

有关信息,我使用 Swift2 和 Xcode7。 如果您需要更多详细信息,请告诉我,我可以为您提供其他东西!

非常感谢您的帮助!相信我,我花了 3 天时间解决这个问题...

你永远不会这样做。核心数据对象只能保存在数据库中。但是,您可以使用 NSUserDefaults 来保存您以后可以检索并用于从核心数据中获取数据的任何密钥。