Ho creato un esempio molto semplice per dimostrare il problema che sto tentando di aggiornare un tipo trasformabile e ottenere la modifica da mantenere tra riavvii dell'app.Come posso ottenere attributi non standard (trasformabili) per aggiornare/salvare e persistere utilizzando Core Data con Swift?
devo un'entità di tipo Destinazione ...
import Foundation
import CoreData
class Destination: NSManagedObject {
@NSManaged var name: String
@NSManaged var location: Location
}
... che ha un attributo semplice nome (di tipo String) e un attributo di tipo Località:
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")
}
}
La posizione è configurata come "trasformabile" in Dati principali, perché ha una struttura che nessuno degli altri tipi di base può gestire.
Utilizzando boilerplate codice Core Data di Apple, ecco un controller della vista che fa semplicemente il seguente:
- ottiene l'AppDelegate necessaria/ManagedApplicationContext riferimento
- recupera una destinazione, se ne esiste uno, crea uno se non
- Stampa il nome e la posizione.indirizzo della destinazione
- Aggiorna il nome e la posizione.indirizzo della destinazione
- Salva le modifiche a the ManagedObjectContext
Quando l'app viene eseguita e rieseguita, verranno mantenute solo le modifiche al nome. Le modifiche apportate all'indirizzo location.address non persistono.
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
}
}
Come è possibile mantenere gli aggiornamenti dell'attributo di posizione della destinazione?
Grazie, l'assegnazione di un nuovo oggetto ha funzionato perfettamente. Ho testato il caso di mutare e reimpostare lo stesso oggetto, ma questo non funziona, probabilmente perché il puntatore non sarebbe mai stato aggiornato in quel caso. Vuole davvero un oggetto nuovo di zecca. –