Skip to content

Instantly share code, notes, and snippets.

@ahbou
Last active March 17, 2021 11:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ahbou/9565cad1f1ee353a7e3578168fa653ef to your computer and use it in GitHub Desktop.
Save ahbou/9565cad1f1ee353a7e3578168fa653ef to your computer and use it in GitHub Desktop.
CoreData discard changes
import UIKit
class ProfileViewController: UIViewController {
/// First create a throwable child context for editing the Profile
private lazy var writeContext: NSManagedObjectContext = {
let result = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
result.automaticallyMergesChangesFromParent = true
result.performAndWait {
// Our main parent context
result.parent = DataSource.shared.mainContext
}
return result
}()
override func viewDidLoad() {
super.viewDidLoad()
title = "My Profile"
// Let's add Cancel and Save buttons
navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(promptToCancel(_:)))
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(save(_:)))
}
/// Present an alert asking the user to confirm discarding his changes
@objc func promptToCancel(_ sender: UIBarButtonItem?) {
guard writeContext.hasChanges else {
closeAndDiscard()
return
}
let alert = UIAlertController(title: "Do you want to leave and discard your changes?", message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Stay", style: .default, handler: nil))
alert.addAction(UIAlertAction(title: "Discard", style: .destructive) { [weak self] _ in
guard let self = self else { return }
self.closeAndDiscard()
})
present(alert, animated: true, completion: nil)
}
// Cancel is confirmed:
private func closeAndDiscard() {
// Return our context to the previous state,
// by discarding all unsaved changes
writeContext.rollback()
dismiss(animated: true, completion: nil)
}
@objc func save(_ sender: UIBarButtonItem?) {
// No need to save if there are no changes
guard writeContext.hasChanges else {
dismiss(animated: true, completion: nil)
}
// Sync save our changes
writeContext.performAndWait { [weak self] in
guard let self = self else { return }
do {
try writeContext.save()
self.didSaveAndClose()
} catch {
print("failed to sync save \(error)")
// Show the error to the user
}
}
}
private func didSaveAndClose() {
// Parent context should be observing these
NotificationCenter.default.post(name: .NSManagedObjectContextDidSave, object: writeContext)
dismiss(animated: true, completion: nil)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment