2014-10-13 7 views
24

Nie jestem pewien, co robię źle tutaj, ale kiedy zapisuję po raz pierwszy w coredata, to działa dobrze. Kiedy próbuję to zastąpić, nie jest.Jak zaktualizować wpis CoreData, który został już zapisany w Swift?

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") 
*/ 

obciążenia Logowanie Dane Func funkcja, która zwraca dane saveLogin

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

Odpowiedz

3

Ty tworzenia wielu nowych LoginData obiektów, ale metoda loadLoginData zawsze zwraca ten sam obiekt, pierwszy od pobrać wyników żądanie.

Chcesz zachować aktualizację tego samego obiektu, więc musisz zmienić metodę saveLoginDetails.

Zamiast tworzyć nowy obiekt (który jest tym, co insertNewObjectForEntityName), należy użyć metody , aby uzyskać istniejący obiekt i zmienić na nim właściwość.

+0

Nie, powinienem używać tego samego za każdym razem. Zdecydowanie robię to źle. – 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")} 

powodzenia

45

Od batchupdate jest bardziej przydatny w większych kawałkach danych, myślę, że jest to bardziej subtelne podejście.

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

Próbowałam mu tłumaczyć trochę do sytuacji, jeśli się nie mylę, ale nie to przetestowane.

fetchRequest.predicate po prostu ustawia filtr w atrybucie userName z encji LoginData, z nazwą (użytkownika) wprowadzoną podczas wywoływania funkcji. Zakładając, że w tym przykładzie masz tylko jedną nazwę użytkownika o tej samej nazwie. Następnie wykonuje żądanie pobrania z danym filtrem, dzięki czemu możesz zmienić jego wartość za pomocą setValue z accesToken, który również wprowadzasz podczas wywoływania funkcji. kod po: jeśli fetchResults.count = 0, tylko wykonuje gdy istnieje nazwa

+0

Musisz umieścić appDel. before managedObjectContext! .executeFetchRequest, więc poprawna linia kodu powinna wyglądać tak: if lets fetchResults = appDel.managedObjectContext! .executeFetchRequest (fetchRequest, error: nil) as? [NSManagedObject] { –

+0

Możesz także po prostu użyć kontekstu, który już zapisałeś w pamięci, bez konieczności ponownego dostępu do niego. Po prostu 'context.executeFetchRequest (...)'. –

+0

Myślę, że lepiej będzie dodać executeFetchRequest w bloku try. błąd nie jest tutaj obsługiwany –

7

Swift> = 2 metoda zwraca teraz non-opcjonalne i generuje błąd w przypadku błędów, które muszą być traktowane z 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

Dziękujemy! Myślę, że możesz potrzebować 'newManagedObject.save()' po ustawieniu wartości, prawda? –

+1

@SSHThis Yes correct. –

0

Aktualizacja dla Swift 4 & XCode 9.2

Aby odpowiedzieć na to pytanie ...

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

Najpierw należy uzyskać odwołanie do swojej AppDelegate i viewContext. Następnie musisz skonfigurować NSFetchRequest dla Entity, którą chcesz zaktualizować, w moim przykładzie, który będzie "Alert". Następnie skonfigurujesz pobieranie, aby znaleźć wynik, którego szukasz. W tym przykładzie mój wynik znalazł Alerty według daty utworzenia i typu alertu.

Aby dowiedzieć się, jak wyszukiwać za pomocą predykatu. Stack Overflow Example & Apple Documentation

Potem context.fetch(fetchRequest), zestaw wyników do wartości chciałem zaktualizować, a rozpatrywane błędów połowu try. Wreszcie 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)") 
}