2014-10-13 5 views
24

Ich bin nicht sicher, was ich hier falsch mache, aber wenn ich das erste Mal in Coredata speichern, funktioniert es gut. Wenn ich versuche, das zu überschreiben, tut es das nicht.Wie aktualisierst du einen CoreData-Eintrag, der bereits in Swift gespeichert wurde?

func testStuff() { 
    var token = loadLoginData() 
    println("Token \(token)") 
    saveLoginData("New Token") 
    var newToken = loadLoginData() 
    println("Token \(newToken)") 
} 

func saveLoginData(accessToken: String) { 
    var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate) 
    var context: NSManagedObjectContext = appDel.managedObjectContext! 
    // save data to core data 
    var loginData = NSEntityDescription.insertNewObjectForEntityForName("LoginData", inManagedObjectContext: context) as NSManagedObject 
    loginData.setValue(accessToken, forKey: "accessToken") 
    context.save(nil) 
    println("Done saving user") 
} 

/* Output 
Token Optional("12345") 
Done saving user 
Token Optional("12345") 
*/ 

laden Zugangsdaten Func die Funktion, die

func loadLoginData() -> String? { 
    var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate) 
    var context: NSManagedObjectContext = appDel.managedObjectContext! 

    var request = NSFetchRequest(entityName: "LoginData") 
    request.returnsObjectsAsFaults = false 

    var results: NSArray = context.executeFetchRequest(request, error: nil)! 
    if (results.count > 0) { 
     var userData: NSManagedObject = results[0] as NSManagedObject 
     var accessToken: String = userData.valueForKey("accessToken") as String 

     return accessToken.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) 

    } else { 
     println("0 results returned, potential error") 
     return nil 
    } 
} 

Antwort

0

Es gibt eine neue Funktion namens Batch Updates auf saveLogin Daten aufruft.

Ich denke, dieser Artikel wird Ihnen helfen:

http://www.bignerdranch.com/blog/new-in-core-data-and-ios-8-batch-updating/

Basicly, was Sie tun, ist die NSBatchUpdateRequest statt NSFetchRequest verwenden, filtern Sie die Ergebnisse mit NSPredicate, den Wert in den Ergebnissen ändern, und die Daten speichern .

Ein weiteres Tutorial in swift:

http://code.tutsplus.com/tutorials/ios-8-core-data-and-batch-updates--cms-22164

3

Sie erstellen mehrere neue LoginData Objekte, aber Ihre loadLoginData Methode ist immer das gleiche Objekt zurückkehrt, die erste von der Anfrage Ergebnisse holen.

Sie möchten dasselbe Objekt aktualisieren, daher müssen Sie Ihre saveLoginDetails Methode ändern.

Anstatt ein neues Objekt zu erstellen (was insertNewObjectForEntityName tut), verwenden Sie die loadLoginDetails Methode, um Ihre bestehende zu erhalten, und ändern Sie die Eigenschaft dort.

+0

Nein, ich sollte jedes Mal dasselbe verwenden. Ich mache das definitiv falsch. – slooker

2
var context:NSManagedObjectContext = appDel.managedObjectContext! 

var en = NSEntityDescription.entityForName("ENTITIES_NAME", inManagedObjectContext: context) 

let batchUpdateRequest = NSBatchUpdateRequest(entity: en!) 
      batchUpdateRequest.resultType = NSBatchUpdateRequestResultType.UpdatedObjectIDsResultType 
      batchUpdateRequest.propertiesToUpdate = ["OBJECT_KEY": "NEWVALUE"] 
      var batchUpdateRequestError: NSError? 
      context.executeRequest(batchUpdateRequest, error:&batchUpdateRequestError) 
      if let error = batchUpdateRequestError {println("error")} 

Glück

45

Seit batchupdate in größeren Datenmengen sinnvoller ist, ich denke, das ein subtiler Ansatz.

func saveLoginData(accessToken: String, userName: String) { 
    var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate) 
    var context: NSManagedObjectContext = appDel.managedObjectContext! 

    var fetchRequest = NSFetchRequest(entityName: "LoginData") 
    fetchRequest.predicate = NSPredicate(format: "userName = %@", userName) 

    if let fetchResults = appDel.managedObjectContext!.executeFetchRequest(fetchRequest, error: nil) as? [NSManagedObject] { 
     if fetchResults.count != 0{ 

      var managedObject = fetchResults[0] 
      managedObject.setValue(accessToken, forKey: "accessToken") 

      context.save(nil) 
     } 
    } 
} 

Ich habe versucht, es ein wenig auf Ihre Situation zu übersetzen, wenn ich mich nicht irre, aber es nicht getestet habe.

fetchRequest.predicate setzt im Grunde den Filter auf das Attribut userName von der Entität LoginData mit dem (Benutzer-) Namen, den Sie beim Aufruf der Funktion eingeben. Angenommen, Sie haben in diesem Beispiel nur einen Benutzernamen mit dem gleichen Namen. Dann führt es eine Abrufanforderung mit dem gegebenen Filter durch, so dass Sie dessen Wert mit setValue mit dem accesToken ändern können, den Sie auch beim Aufruf der Funktion eingeben. der Code nach: wenn fetchResults.count = 0, führt nur dann, wenn der Benutzername

+0

Sie müssen appDel setzen. vor managedObjectContext! .executeFetchRequest, so sollte die korrekte Codezeile wie folgt aussehen: Wenn fetchResults = appDel.managedObjectContext! .executeFetchRequest (fetchRequest, error: nil) als? [NSManagedObject] { –

+0

Sie können auch Ihren Kontext verwenden, den Sie bereits im Speicher gespeichert haben, ohne ihn erneut aufrufen zu müssen. Nur 'context.executeFetchRequest (...)'. –

+0

Ich denke, es wird besser sein, executeFetchRequest in try Block hinzuzufügen. Fehler hier nicht behandelt –

7

Swift existiert> = 2 die Methode gibt jetzt ein nicht optional und wirft einen Fehler im Fehlerfall, die mit behandelt werden müssen try-catch:

let context = self.fetchedResultsController.managedObjectContext 
    let entity = self.fetchedResultsController.fetchRequest.entity! 

    let fetchRequest = NSFetchRequest(entityName:entity.name!) 
    fetchRequest.predicate = NSPredicate(format: "notificationId = 13") 

    do { 
     let list = try context.executeFetchRequest(fetchRequest) as? [NSManagedObject] 
     if list!.count == 0 // Check notificationId available then not save 
     { 
      let newManagedObject = NSEntityDescription.insertNewObjectForEntityForName(entity.name!, inManagedObjectContext: context) 
      newManagedObject.setValue("This is first message13", forKey: "message") 
      newManagedObject.setValue(1, forKey: "appId") 
      newManagedObject.setValue(13, forKey: "notificationId") 
      newManagedObject.setValue("First one", forKey: "tital") 
     } 
     // success ... 
    } catch let error as NSError { 
     // failure 
     print("Fetch failed: \(error.localizedDescription)") 
    } 
+0

Danke! Ich denke, Sie brauchen 'newManagedObject.save()' nach Einstellungen der Werte, richtig? –

+1

@SSHDieses ist korrekt. –

0

Aktualisiert für Swift 4 & XCode 9.2

Um Ihre Frage zu beantworten ...

How do you update a CoreData entry that has already been saved in Swift?

Als erstes müssen Sie einen Verweis auf Ihre AppDelegate und viewContext zu bekommen. Sie müssen dann eine NSFetchRequest für die Entität einrichten, die Sie aktualisieren möchten, in meinem Beispiel wäre das "Alert". Sie richten dann Ihren Abruf ein, um das Ergebnis zu finden, nach dem Sie suchen. Im Beispiel hat mein Ergebnis Warnungen nach ihrem Erstellungsdatum und ihrem Benachrichtigungstyp gefunden.

Weitere Informationen zum Abfragen mithilfe eines Vergleichselementes. Stack Overflow Example & Apple Documentation

ich dann context.fetch(fetchRequest), stellen Sie die Ergebnisse auf den Wert I aktualisieren wollte, und befasste sich mit Fehlern in einem Versuch zu fangen. Schließlich I context.save().

let appDelegate = UIApplication.shared.delegate as! AppDelegate 
let context = appDelegate.persistentContainer.viewContext 
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Alert") 

fetchRequest.predicate = NSPredicate(format: "creationDate = %@ AND alertType = %&", 
             argumentArray: [creationDate, alertType]) 

do { 
    let results = try context.fetch(fetchRequest) as? [NSManagedObject] 
    if results?.count != 0 { // Atleast one was returned 

     // In my case, I only updated the first item in results 
     results[0].setValue(yourValueToBeSet, forKey: "yourCoreDataAttribute") 
    } 
} catch { 
    print("Fetch Failed: \(error)") 
} 

do { 
    try context.save() 
    } 
catch { 
    print("Saving Core Data Failed: \(error)") 
} 
Verwandte Themen