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
How to Handle Image Scale on All the Available iPhone Resolutions
Using Weak Self in Dispatch_Async Function
Where to Store Global Constants in an iOS Application
Get Safe Area Inset Top and Bottom Heights
Application Loader Stuck at "Authenticating with the Itunes Store" When Uploading an iOS App
Uistackview Distribution Fill Equally
Creating Delegates on the Spot with Blocks
Is Grouptableviewbackgroundcolor Deprecated on iOS 6
How to Use Nsurlsessiondatatask in Swift
How to Get a View's Current Width and Height When Using Autolayout Constraints
Nsmutableurlrequest Timeout Interval Not Taken into Consideration for Post Requests
Add Child View Controller to Current View Controller
Get an Array of Property Values from an Object Array
How to Create a Uilabel with Strikethrough Text
Prevent Deploying (Disable) Watchkit App with iOS iPhone App in Xcode
How to Create a Colored 1X1 Uiimage on the iPhone Dynamically