我已经构建了一个非常基本的示例来演示我尝试更新可转换类型并在应用程序重新启动之间保持更改的问题.
我有一个Destination类型的实体…
import Foundation import CoreData class Destination: NSManagedObject { @NSManaged var name: String @NSManaged var location: Location }
…具有简单的名称属性(String类型)和类型为Location的属性:
import Foundation class Location: NSObject,NSCoding { var address: String var latitude: Double var longitude: Double required init?(coder aDecoder: NSCoder) { address = aDecoder.decodeObjectForKey("Address") as? String ?? "" latitude = aDecoder.decodeObjectForKey("Latitude") as? Double ?? 0.0 longitude = aDecoder.decodeObjectForKey("Longitude") as? Double ?? 0.0 super.init() } init(address: String,latitude: Double,longitude: Double) { self.address = address self.latitude = latitude self.longitude = longitude super.init() } func encodeWithCoder(aCoder: NSCoder) { aCoder.encodeObject(address,forKey: "Address") aCoder.encodeObject(latitude,forKey: "Latitude") aCoder.encodeObject(longitude,forKey: "Longitude") } }
位置在Core Data中配置为“可转换”,因为它具有其他基本类型都无法处理的结构.
使用Apple的样板核心数据代码,这里是一个视图控制器,它只执行以下操作:
>获取必要的appDelegate / ManagedApplicationContext引用
>如果存在目的地,则获取目的地,否则创建一个目的地
>打印目的地的名称和location.address
>更新目标的名称和location.address
>保存对ManagedObjectContext的更改
当应用程序运行并重新运行时,只会对名称进行更改.对location.address所做的更改不会保留.
import UIKit import CoreData class ViewController: UIViewController { var appDelegate: AppDelegate! var context: NSManagedObjectContext! override func viewDidLoad() { super.viewDidLoad() updateDestination() } func updateDestination() { var destination: Destination appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate context = appDelegate.managedObjectContext if let dest = fetchOneDestination() { destination = dest } else { destination = create()! } print("destination named: \(destination.name),at: \(destination.location.address)") destination.name = "New name of place that will update and persist" destination.location.address = "123 main st (change that will never persist)" appDelegate.saveContext() } func create() -> Destination? { guard let newDestination = NSEntityDescription.insertNewObjectForEntityForName("Destination",inManagedObjectContext: context) as? Destination else { return nil } newDestination.name = "Original name of place that can be updated" newDestination.location = Location(address: "100 main st",latitude: 34.051145,longitude: -118.243595) return newDestination } func fetchOneDestination() -> Destination? { let request = NSFetchRequest() request.entity = NSEntityDescription.entityForName("Destination",inManagedObjectContext: context) do { let fetchResults = try context.executeFetchRequest(request) if fetchResults.count > 0 { if let dest = fetchResults[0] as? Destination { return dest } } } catch {} return nil } }
如何更新目标的位置属性?
解决方法
核心数据无法跟踪该对象的脏状态,因为它不了解其内部.而不是改变对象,创建一个副本,改变它,然后设置新对象.它可能会变异,然后重新设置相同的对象,不确定,没有测试它.
您可以检查,只是改变地址,然后询问托管对象是否有更改,如果没有则则不会保存.