How to Update a Coredata Entry That Has Already Been Saved in Swift

In Core Data, how to do `if exists update else insert` in swift 4?

try this :

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

if let fetchResults = appDel.managedObjectContext!.executeFetchRequest(fetchRequest, error: nil) as? [NSManagedObject] {
if fetchResults.count != 0 {
// update
var managedObject = fetchResults[0]
managedObject.setValue(accessToken, forKey: "accessToken")

context.save(nil)
} else {
//insert as new data
}
}

Cheers :)

What's the syntax for updating existing attributes in core data compared to saving a new object in core data?


  • The first syntax inserts a new record – you have to save the context afterwards.

  • The second syntax fetches existing data and updates a record.

However to update a specific record you have to add a predicate and most likely you don't want to update the name and the gender attributes

let name = "John Doe"
let fetchRequest : NSFetchRequest<Person> = Person.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "name == %@", name)
let results = try context.fetch(fetchRequest)
if let container = results.first {
// container.name = some_string
// container.gender = some_string
container.last_occupation = custom_object
try context.save()
context.refresh(transformableContainer, mergeChanges: false)
}

How to replace/update data being save in core data

To update an existing record you have to fetch it by given ID and check if the record exists.

If it exists, update it.

If not, create a new one.

ApiSession.shared.send(request) { response in
if let err = response.error {
print("Failed to get youtube data:", err)
return
}

guard let results = response.value else { return }
self.nextPageToken = results.nextPageToken
let context = CoreDataManager.shared.persistenceContainer.viewContext
results.items.forEach({ result in
let request: NSFetchRequest<Video> = Video.fetchRequest()
request.predicate = NSPredicate(format: "videoId == %@", result.id.videoID) // if videoID is Int change the placeholder to `%ld`
do {
let videos = try context.fetch(request)
if let video = videos.first {
video.videoTitle = result.snippet.title
self.videos.append(video)
} else {
let video = NSEntityDescription.insertNewObject(forEntityName: "Video", into: context) as! Video
video.videoTitle = result.snippet.title
video.videoId = result.id.videoID
}
} catch {
print("Failed to fetch video:", error)
}
})
do {
try context.save()
} catch {
print("Failed to save video:", error)
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}

Update an object on core data swift 4

Please read the error message. It's very clear. In setValue you are passing a String (via String Interpolation) rather than expected Int or NSNumber

object.setValue(jobId, forKey: "jobId")

or

object.setValue(NSNumber(value: jobId), forKey: "jobId")

But the best and recommended way is dot notation

object.jobId = jobId

Updating CoreData Entity or saving a new one

Don't let Core Data scare you. It can be a fine way to save local data and despite some comments, it is not slow when done right. In fact, Core Data can be quite fast.

You can simplify your code a lot by using your Object class in a more normal fashion instead of using setValue calls. Your create code can be changed to this:

// CODE TO SAVE A NEW MATCH FOR THE FIRST TIME
if let matchData = NSEntityDescription.insertNewObject(forEntityName: "MatchData", into: context) as? MatchData {

matchData.isRealTime = isRealTime
matchData.myScore = currentScore?[0]
matchData.scoreArray = currentScore?.map{String($0)}.joined(separator: "\t") // IS THIS CODE CORRECT? I'M TRYING TO SAVE AN ARRAY OF INTS INTO A SINGLE STRING
// You can certainly save it this way and code it in and out. A better alternative is to have a child relationship to another managed object class that has the scores.
matchData.playerArray = currentPlayers?.joined(separator: "\t")
matchData.isWaiting = true
matchData.matchID = matchID
matchData.gameLog = gameLog
}

This is a much more readable and normal way to set your object properties. Any time you change a property on a core data managed object then it will get saved the next time you save the context.

As far as finding a current record that matches the ID, I like to add classes like that to my Managed Object class itself:

class func findByID(_ matchID: String) -> MatchData? {
let myAppDelegate = UIApplication.shared.delegate as! AppDelegate
let context = myAppDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "MatchData")
let idPredicate = NSPredicate(format: "matchID = \(matchID)", argumentArray: nil)
request.predicate = idPredicate
var result: [AnyObject]?
var matchData: MatchData? = nil
do {
result = try context.fetch(request)
} catch let error as NSError {
NSLog("Error getting match: \(error)")
result = nil
}
if result != nil {
for resultItem : AnyObject in result! {
matchData = resultItem as? MatchData
}
}
return matchData
}

Then any place you need the match data by ID you can call the class function:

if let matchData = MatchData.findByID("SomeMatchID") {
// Match exists
}

How to update existing object in core data ? [Swift]

Your current code is:

if let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext {

let place : Places = Places()
place.isFavourite = cell.isFavouriteLabel.text
do{
try managedObjectContext.save()
} catch let error as NSError{
print(error)

}
}

That would create a new place (if it worked), but you need to update an existing one.

You have the places returned from managedObjectContext.executeFetchRequest.

So you need to get something like places[index_of_the_cell_in_question].isFavourite = cell.isFavouriteLabel.text

and then managedObjectContext.save().



Related Topics



Leave a reply



Submit