How to create CoreData database swift4 - ios

Plese share some sample code snippet for database save details and fetch saved details in swift 4

This is my answer
Step 1 : Create Coredata Stack Class see below
var coreDataStack: CoreDataStack = CoreDataStack() // add this line on appDelegate
class Stack
{
lazy var managedObjectModel: NSManagedObjectModel = {
let modelUrl = Bundle.main.url(forResource: "Model", withExtension: "momd")!
return NSManagedObjectModel(contentsOf: modelUrl)!
}()
lazy var peristentStoreCoordinator: NSPersistentStoreCoordinator = {
let coordinator: NSPersistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let applicationDocumentsDirectory: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last!
let persistentStoreUrl: URL = applicationDocumentsDirectory.appendingPathComponent("Model.sqlite")
do {
try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: persistentStoreUrl, options: nil)
}
catch {
fatalError("Persistent store error! \(error)")
}
return coordinator
}()
lazy var managedObjectContext: NSManagedObjectContext = {
let managedObjectContext: NSManagedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = self.peristentStoreCoordinator
return managedObjectContext
}()
func saveContext() {
if self.managedObjectContext.hasChanges {
do {
try self.managedObjectContext.save()
}
catch {
fatalError("There was an error saving the managed object context \(error)")
}
}
}
}
Step 2 : Create entity
Step 3 : Create ManagedObjectModelSubclass -- Editor -> ManagedObjectModelSubclass
Step 4 : import core data on class and add below code
var person = [Person]() //[Person] here denote subclassclass name
var appDelegate = UIApplication.shared.delegate as! AppDelegate
let personEntity: NSEntityDescription? = NSEntityDescription.entity(forEntityName: "EntityName", in: self.appDelegate.coreDataStack.managedObjectContext)
if personEntity != nil {
let person1: Person = Person(entity: personEntity!, insertInto: self.appDelegate.coreDataStack.managedObjectContext)
person1.name = "name"
person1.country = "US"
person1.age = "26"
person1.place = "NewYork"
}
Step 5 : For fetch data use below code
var persons: [Person] = [] // subclass name
var appDelegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate
var listdata = [ModelClass]() // create a modelclass object
func fetchDemoData() {
let fetchRequest: NSFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "EntityName")
do {
if let results = try self.appDelegate.coreDataStack.managedObjectContext.fetch(fetchRequest) as? [NSManagedObject] {
let personList: [Person]? = results as? [Person]
if personList != nil {
self.persons = personList!
for eachData in persons {
let name = eachData.name as String!
let username = eachData.age as String!
let email = eachData.country as String!
let address = eachData.place as! [String : Any]
self.listdata.append(ModelClass(name: name!, username: username!,email : email!,address : address))
}
//self.tableview.reloadData()
}
}
}
catch {
fatalError("There was an error fetching the items")
}
}

let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Users", in: context)
let newUser = NSManagedObject(entity: entity!, insertInto: context)
newUser.setValue("Shashikant", forKey: "username")
newUser.setValue("1234", forKey: "password")
newUser.setValue(1, forKey: "age")
do {
try context.save()
} catch {
print("Failed saving")
}
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")
//request.predicate = NSPredicate(format: "age = %#", "12")
request.returnsObjectsAsFaults = false
do {
let result = try context.fetch(request)
for data in result as! [NSManagedObject] {
print(data.value(forKey: "id") as! String)
print(data.value(forKey: "username") as! String)
}
} catch {
print("Failed")
}

import UIKit
import CoreData
class ViewController: UIViewController {
#IBOutlet weak var txtName: UITextField!
#IBOutlet weak var txtId: UITextField!
#IBOutlet weak var txtMark: UITextField!
#IBOutlet weak var labelStatus: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func buutonSave(_ sender: Any) {
let appDelegateObject:AppDelegate = UIApplication.shared.delegate as! AppDelegate
let managedObject:NSManagedObjectContext = appDelegateObject.persistentContainer.viewContext
let entityDescription =
NSEntityDescription.entity(forEntityName: "Student",
in: managedObject)
var student = NSManagedObject(entity: entityDescription!, insertInto: managedObject)
[student .setValue(self.txtName.text, forKey: "name")]
[student .setValue(self.txtId.text, forKey: "id")]
[student .setValue(self.txtMark.text, forKey: "mark")]
labelStatus.text = "Contact Saved"
}
#IBAction func buttonFind(_ sender: Any) {
let appDelegateObject:AppDelegate = UIApplication.shared.delegate as! AppDelegate
let managedObject:NSManagedObjectContext = appDelegateObject.persistentContainer.viewContext
let entityDescription =
NSEntityDescription.entity(forEntityName: "Student",
in: managedObject)
let request = NSFetchRequest<NSFetchRequestResult>()
request.entity = entityDescription
let pred = NSPredicate(format: "(name = %#)", txtName.text!)
request.predicate = pred
do {
var results =
try managedObject.fetch(request)
if results.count > 0 {
let match = results[0] as! NSManagedObject
txtName.text = match.value(forKey: "name") as? String
txtId.text = match.value(forKey: "id") as? String
txtMark.text = match.value(forKey: "mark") as? String
labelStatus.text = "Matches found: \(results.count)"
} else {
labelStatus.text = "No Match"
}
} catch let error as NSError {
labelStatus.text = error.localizedFailureReason
}
}
}

//CoreDataRose
ad = (UIApplication.shared.delegate as! AppDelegate) moc = ad.persistentContainer.viewContext
actorEntity = NSEntityDescription.entity(forEntityName: "Actors", in: moc)
func fetch() {
let fetchReq = NSFetchRequest<NSFetchRequestResult>(entityName: "Actors")
do{
let actorsArr = try moc.fetch(fetchReq)
for i in 0..<actorsArr.count
{
let mo:NSObject = actorsArr[i] as! NSManagedObject
print(mo.value(forKey: "empFName")!)
DispatchQueue.main.async {
actorsArray.append(actors(firstName: (mo.value(forKey: "empFName") as? String), lastName: (mo.value(forKey: "empLName") as? String ), age: (mo.value(forKey: "empAge") as? Int)))
}
}
}catch{
print("Error Message")
}
}
#IBAction func submitBtn(_ sender: Any) {
// var secondView = storyboard?.instantiateViewController(withIdentifier: "DisplayView") as! DisplayView
// secondView.firstView = self
// present(secondView, animated: true)
actorsArray.append(actors(firstName: "\(firstNameTF.text!)", lastName: "\(lastNameTF.text!)", age: ageTF.text! as? Int))
var mo2 = NSManagedObject(entity: actorEntity, insertInto: moc)
mo2.setValue(firstNameTF.text, forKey: "empFName")
mo2.setValue(lastNameTF.text, forKey: "empLName")
mo2.setValue(Int(ageTF.text!), forKey: "empAge")
do{
try moc.save()
}catch{
print("Error")
}
}
#IBAction func chooseImageButton(_ sender: Any) {
let image = UIImagePickerController()
image.delegate = self
image.sourceType = UIImagePickerController.SourceType.photoLibrary
image.allowsEditing = false
self.present(image, animated: true)
{
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage
{
importImage.image = image
}
else{
print("error message")
}
self.dismiss(animated: true, completion: nil)
}

Related

Core data entity manager

I want to write class for manage all entity that i have in my application.
there is my code fore managerClass for one custom entity, but I have a problem to set manageObject type in this context.
public func clearEntityContex() {
let fetchRequest: NSFetchRequest<Shop> = Shop.fetchRequest()
if let fetchResult = try? self.stack.mainQueueContext.fetch(fetchRequest){
for user : Shop in fetchResult {
self.stack.mainQueueContext.delete(user as Shop)
}
do {
try stack.mainQueueContext.save()
}
catch {
debugPrint(error.localizedDescription)
}
}
}
//MARK: _fetch Contex
public func fetchsShopEntity() -> [Shop]? {
var shops : [Shop]?
let fetchRequest: NSFetchRequest<Shop> = Shop.fetchRequest()
do {
let fetchResult =
try self.stack.mainQueueContext.fetch(fetchRequest)
if fetchResult.count > 0 {
shops = fetchResult
}
}
catch {
fatalError("Failed to fetch Account: \(error)")
}
return shops
}
//MARK: _save entity
public func saveEntityInModel(entityItem : Shop){
if let entity = NSEntityDescription.entity(forEntityName: "Shop", in: self.stack.mainQueueContext) {
if let contex = NSManagedObject(entity: entity, insertInto: self.stack.mainQueueContext) as? Shop {
contex.packID = entityItem.packID
contex.packName = entityItem.packName
contex.packImage = entityItem.packImage
contex.priceDolar = entityItem.priceDolar
contex.packDescription = entityItem.packDescription
do {
try stack.mainQueueContext.save()
}
catch {
debugPrint(error.localizedDescription)
}
}
}
}
for example i want to write method that can clear any entityContext. but i cant pass manageObject to this method.
public func clearEntityContex(entityObject: NSManagedObject) {
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = entityObject.fetchRequest()
if let fetchResult = try? self.stack.mainQueueContext.fetch(fetchRequest){
for entity in fetchResult {
self.stack.mainQueueContext.delete(entity as entityObject)
}
do {
try stack.mainQueueContext.save()
}
catch {
debugPrint(error.localizedDescription)
}
}
}
how can solve pass NSManagedObject to this method?
thanks for all reply
Here's a more generic implementation that we use in our projects.
import CoreData
class ACSwiftCoreData: ACCoreDataPlugin {
let managedObjectModelName: String
let databasePath: URL
init(managedObjectModelName: String, databasePath: URL) {
self.managedObjectModelName = managedObjectModelName
self.databasePath = databasePath
}
// MARK: Managed Object Contexts
private var sharedContext: NSManagedObjectContext?
func getSharedManagedObjectContext() throws -> NSManagedObjectContext {
if let sharedContext = self.sharedContext {
return sharedContext
}
let context = try self.createManagedObjectContext()
self.sharedContext = context
return context
}
func createManagedObjectContext() throws -> NSManagedObjectContext {
let storeCoordinator = try self.getPersistentStoreCoordinator()
let managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = storeCoordinator
managedObjectContext.mergePolicy = NSMergePolicy(merge: NSMergePolicyType.mergeByPropertyObjectTrumpMergePolicyType)
return managedObjectContext
}
// MARK: Creating Entities
func createEntityInSharedContext<EntityType>(_ entityName: String) throws -> EntityType {
let context = try self.getSharedManagedObjectContext()
return try self.createEntity(entityName, context: context)
}
func createEntity<EntityType>(_ entityName: String, context: NSManagedObjectContext) throws -> EntityType {
let entity = NSEntityDescription.insertNewObject(forEntityName: entityName, into: context)
guard let expectedEntity = entity as? EntityType else {
throw self.errorWithMessage("ACSwiftCoreData: Entity for name \(entityName) does not match class \(EntityType.self).")
}
return expectedEntity
}
// MARK: Saving Entity
func saveEntity(_ entity: NSManagedObject) throws {
guard let context = entity.managedObjectContext else {
throw errorWithMessage("ACSwiftCoreData: Cannot save Entity. ManagedObjectContext is missing.")
}
if context.hasChanges {
try context.save()
}
}
// MARK: Delete Entity
func deleteEntity(_ entity: NSManagedObject) throws {
guard let context = entity.managedObjectContext else {
throw errorWithMessage("ACSwiftCoreData: Cannot delete Entity. ManagedObjectContext is missing.")
}
context.delete(entity)
try context.save()
}
// MARK: Fetch Requests
func fetchEntitiesInSharedContext<EntityType: AnyObject>(_ entityName: String, predicate: NSPredicate?) -> [EntityType] {
guard let context = try? self.getSharedManagedObjectContext() else {
return [EntityType]()
}
return self .fetchEntities(entityName, context: context, predicate: predicate)
}
func fetchEntities<EntityType: AnyObject>(_ entityName: String, context: NSManagedObjectContext, predicate: NSPredicate?) -> [EntityType] {
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
fetchRequest.predicate = predicate
let results = try? context.fetch(fetchRequest)
guard let resultEntitys = results as? [EntityType] else {
return [EntityType]()
}
return resultEntitys
}
// MARK: Technical Details
private var storeCoordinator: NSPersistentStoreCoordinator?
private func getPersistentStoreCoordinator() throws -> NSPersistentStoreCoordinator {
if let storeCoordinator = self.storeCoordinator {
return storeCoordinator
}
let model = try self.getManagedObjectModel()
let storeCoordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
var options = [AnyHashable: Any]()
options[NSMigratePersistentStoresAutomaticallyOption] = true
options[NSInferMappingModelAutomaticallyOption] = true
try storeCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: self.databasePath, options: options)
self.storeCoordinator = storeCoordinator
return storeCoordinator
}
private var objectModel: NSManagedObjectModel?
private func getManagedObjectModel() throws -> NSManagedObjectModel {
if let objectModel = self.objectModel {
return objectModel
}
let momName = self.managedObjectModelName
guard let modelUrl = Bundle.main.url(forResource: momName, withExtension:"momd") else {
throw self.errorWithMessage("ACSwiftCoreData: DataModel Url could not be created.")
}
guard let objectModel = NSManagedObjectModel(contentsOf: modelUrl) else {
throw self.errorWithMessage("ACSwiftCoreData: DataModel could not be loaded.")
}
self.objectModel = objectModel
return objectModel
}
// MARK: Error handling
private func errorWithMessage(_ message: String) -> NSError {
let userInfo = [NSLocalizedDescriptionKey: message]
let error = NSError(domain: "com.appcron.accomponents", code: 0, userInfo: userInfo)
return error
}
}
In some project that I made and when I used CoreData, I usually create a Singleton with function to fetch, save and delete a CoreData object.
This is my CoreDataController:
import Foundation
import CoreData
import UIKit
final class CoreDataController {
static let sharedInstances = CoreDataController()
private var context: NSManagedObjectContext
private init(){
let application = UIApplication.shared.delegate as! AppDelegate
self.context = application.persistentContainer.viewContext
}
func loadAll() {
print("Fetch from CoreData")
let fetchRequest: NSFetchRequest<YourEntity> = YourEntity.fetchRequest()
do {
let entityArray = try self.context.fetch(fetchRequest)
guard entityArray.count > 0 else {
print("There aren't element in CoreData "); return}
} catch let error {
print("FetchRequest error")
print(" Print error: \n \(error) \n")
}
}
func save(entityToSave: String, item: String){
let entity = NSEntityDescription.entity(forEntityName: entityToSave, in: self.context)
let newItem = YourEntity(entity: entity!, insertInto: self.context)
newItem.name = item
do {
try self.context.save()
} catch let error {
print("Problem with \(newItem)")
print(" Print error: \n \(error) \n")
}
print("Element \(newItem) saved in CoreData")
}
func loadFromName(entityName:String, name: String) -> Any {
let request = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
request.returnsObjectsAsFaults = false
let predicate = NSPredicate(format: "yourEntityAttribute = %#", yourEntityAttribute)
request.predicate = predicate
let items = self.loadFromFetchRequest(request: request)
return items[0]
}
private func loadFromFetchRequest(request: NSFetchRequest<NSFetchRequestResult>) -> [Any] {
var array = [Any]()
do {
array = try self.context.fetch(request)
guard array.count > 0 else {print("There aren't element in CoreData"); return []}
for item in array {
print("Item: \(item)")
}
} catch let error {
print("FetchRequest Error")
print(" Print Error: \n \(error) \n")
}
return array
}
func delete(entityName: String, name: String) {
let item = self.loadFromName(entityName: entityName, name: name)
self.context.delete(item as! NSManagedObject)
do {
try self.context.save()
} catch let error {
print("Deleting problem")
print("Print Error: \n \(error) \n")
}
}
func loadData(entity: String) -> [YourEntity] {
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entity)
fetchRequest.returnsObjectsAsFaults = false
var data = [YourEntity]()
do {
data = try self.context.fetch(fetchRequest) as! [YourEntity]
} catch let error {
print("Print Error: \n \(error) \n")
}
return data
}
}
When you have to call, just write:
CoreDataController.sharedInstances.save(entityToSave: "Profile", item: textfield.text!)
or other functions!!!
I hope this is useful for you.
For use this Class with every Entity you can write like that:
let entity = NSEntityDescription.entity(forEntityName: entityToSave, in: self.context)
let newItem: Any
switch entityToSave {
case "YourEntity":
newItem = YourEntity(entity: entity!, insertInto: self.context)
(newItem as! YourEntity).entityAttribute = firstItem
(newItem as! YourEntity).entityAttribute = secondItem
case "YourEntity2":
newItem = YourEntity2(entity: entity!, insertInto: self.context)
(newItem as! YourEntity2).entityAttribute = firstItem
(newItem as! YourEntity2).entityAttribute = secondItem
case "YourEntity3":
newItem = YourEntity3(entity: entity!, insertInto: self.context)
(newItem as! YourEntity3).entityAttribute = firstItem
(newItem as! YourEntity3).entityAttribute = secondItem
case "YourEntity4":
newItem = YourEntity4(entity: entity!, insertInto: self.context)
(newItem as! YourEntity4).entityAttribute = firstItem
(newItem as! YourEntity4).entityAttribute = secondItem
default:
fatalError("Error in entityToSave function")
}
do {
try self.context.save()
} catch let error {
print("Problem to save \(newItem)")
print("Print Error: \n \(error) \n")
}
print("Element \(newItem) saved correctly")
}

sort coreData fetch (swift4)

Right now my code is using NSPredicate or sort descriptor to basically just collect a name. I would like NSPredicate to sort all of the names from a-z thats it.
COREDATAHANDLER
class coreDataHandler: NSObject {
private class func getContext() -> NSManagedObjectContext{
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}
class func saveObject(username:String, password:String) -> Bool{
let context = getContext()
let entity = NSEntityDescription.entity(forEntityName: "User", in: context)
let managedObject = NSManagedObject(entity: entity!, insertInto: context)
managedObject.setValue(username, forKey: "username")
managedObject.setValue(password, forKey: "password")
do {
try context.save()
return true
} catch {
return false}
}
class func filterData() -> [User]? {
let conttext = getContext()
let fetchRequest:NSFetchRequest<User> = User.fetchRequest()
var user:[User]? = nil
var predicate = NSPredicate(format: "username contains[d] %#" ,"duke")
fetchRequest.predicate = predicate
do {
user = try conttext.fetch(fetchRequest)
return user
}catch {
return user
}
}
VIEWCONTROLLER
user = coreDataHandler.filterData()
for i in user! {
print("Judou : \(i.username!)")
}
If you want your user array to be sorted by username and then password, I would add a class function to your CoreDataHandler class to get a sorted array:
class func getSortedData() -> [User]? {
let conttext = getContext()
let fetchRequest:NSFetchRequest<User> = User.fetchRequest()
var user:[User]? = nil
var nameSort = NSSortDescriptor(key:"username", ascending:true)
var passwordSort = NSSortDescriptor(key:"password", ascending:false)
fetchRequest.sortDescriptors = [nameSort, passwordSort]
do {
user = try conttext.fetch(fetchRequest)
return user
} catch {
return user
}
}
Then in your view controller, use this new function to get the sorted array:
user = coreDataHandler.getSortedData()
for i in user! {
print("Judou : \(i.username!), Password:\(i.password)")
}
In swift 4 or swift 5, you can use
func sortlist(){
//1
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
//2
let fetchRequest =
NSFetchRequest<NSManagedObject>(entityName: "User")
let sort = NSSortDescriptor(key: "username", ascending: false)
fetchRequest.sortDescriptors = [sort]
//3
do {
let langugeCodes = try managedContext.fetch(fetchRequest)
for result in langugeCodes as [NSManagedObject] {
var username:String = result.value(forKey: "username")! as! String
var password:String = result.value(forKey: "password")! as! String
print("username==>",username)
print("name==>",name)
}
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}

how to save and fetch at the same time in coredata swift3

In my current project I am saving datas like(image attributes) into coredata but while fetching instantly it's not giving me the exact numbers of data.Most of the time giving less number of data than what I saved.But in log it's showing that all datas are successfully saved.My questing is before fetching I can see the log so there is no question of that the datas are not saved properly.Please help me to get out of this problem.
func saveImageDetails(aImage: UIImage?, imageUrl: String!, phAsset: PHAsset!, objectType: String, objectId: String, objectName:String,location: String?){
if let newImage = aImage {
let date = HelpherMethod.sharedInstance().toLocalTime(Date())
let resource = PHAssetResource.assetResources(for: phAsset!).first
let fileName = resource?.originalFilename
var imageName : String?
let timestamp = date?.timeIntervalSince1970
print(String(format:"%.0f",timestamp!))
let currentTimeStamp = String(format:"%.0f",timestamp!)
imageName = String(format:"%#_%#",AuthService.instance.userName,currentTimeStamp)
let mImage = self.objectWithTypePredicate(aType: "Image", predicate: NSPredicate(format:"(imageName == %#)",imageName!), canCreate: true)
mImage?.setValue(fileName, forKey: "fileName")
mImage?.setValue(date, forKey: "dateTime")
mImage?.setValue(objectId, forKey: "objectId")
mImage?.setValue(objectType, forKey: "objectType")
mImage?.setValue(objectName, forKey: "objectName")
mImage?.setValue(newImage, forKey: "image")
mImage?.setValue(imageName, forKey: "imageName")
mImage?.setValue(imageUrl, forKey: "imageUrl")
if let loc = location {
mImage?.setValue(loc, forKey: "location")
}
mImage?.setValue("progress", forKey: "status") //Status failed for not uploaded // progress for processing// success for sync// at the initial level all status are set to progress
do {
try mImage?.managedObjectContext?.save()
} catch {
fatalError("Failure to save context: \(error)")
}
}
}
//fethcing from coredata
func fetchRecordsWithClassName(entityName: String , sortingKey: String , isAscending: Bool , predicate: NSPredicate? , isAllrecord: Bool ) -> Array<Any>{
let managedContext = PLMCoreDataInstance.managedObjectContext
// Initialize Fetch Request
let fetchRequest = NSFetchRequest<NSFetchRequestResult>() as NSFetchRequest
//create entity description
let entityDescription = NSEntityDescription.entity(forEntityName: entityName, in: managedContext!)
let sortDescriptor = NSSortDescriptor(key: sortingKey, ascending: isAscending)
fetchRequest.sortDescriptors = [sortDescriptor]
// optional chaining
if let newPredicate = predicate {
fetchRequest.predicate = newPredicate
}
//Configure fetch Request
fetchRequest.entity = entityDescription
do {
if let results = try? managedContext?.fetch(fetchRequest) {
return results!
}
}
return []
}
Finally, it worked by using the below code and using parent-child context like creating private managedObjectContext in a background thread.
func saveImageDetailsFromArray(dictionary : Dictionary<String, Any>,descriptiondictionary : Dictionary<String, Any>?, selectedImages: Array<PHAsset>, objectType: String, objectId: String, objectName:String,location: String?,completionHandler :#escaping PLMCoreDataCompletionHandler){
let moc = self.managedObjectContext //Our primary context on the main queue
let privateMOC = self.backgroundContext
for phAsset in selectedImages{
privateMOC?.perform {
let index = selectedImages.index(of: phAsset)
let date = HelpherMethod.sharedInstance().toLocalTime(Date())
let timestamp = date?.timeIntervalSince1970
print(String(format:"%f",timestamp!))
let currentTimeStamp = String(format:"%f",timestamp!)
var imageName : String?
imageName = String(format:"%#_%#",AuthService.instance.userName,currentTimeStamp)
let newImage = dictionary[phAsset.localIdentifier]
let resource = PHAssetResource.assetResources(for: phAsset).first
let fileName = resource?.originalFilename
let userName = AuthService.instance.userName
let mImage = NSEntityDescription.insertNewObject(forEntityName: "Image", into: privateMOC!) as! Image
mImage.setValue(fileName, forKey: "fileName")
mImage.setValue(date, forKey: "dateTime")
mImage.setValue(objectId, forKey: "objectId")
mImage.setValue(objectType, forKey: "objectType")
mImage.setValue(objectName, forKey: "objectName")
mImage.setValue(newImage, forKey: "image")
mImage.setValue(imageName, forKey: "imageName")
mImage.setValue(phAsset.localIdentifier, forKey: "imageUrl")
mImage.setValue(userName, forKey: "userName")
mImage.setValue("progress", forKey: "status")
if let loc = location {
mImage.setValue(loc, forKey: "location")
}
if let dict = descriptiondictionary{
if let description = dict[phAsset.localIdentifier] {
mImage.setValue(description, forKey: "comment")
}
}
do {
try privateMOC?.save()
moc.performAndWait {
do {
try moc.save()
print("###########save context: \(String(describing: mImage))")
print("###########imageName: \(String(describing: imageName)))")
DispatchQueue.main.async {
if(index == selectedImages.count - 1){
print("###########index: \(String(describing: index)))")
completionHandler(true)
}
}
} catch {
fatalError("Failure to save context: \(error)")
}
}
} catch {
fatalError("Failure to save context: \(error)")
}
}
}
}
VIEWCONTROLLER--1:
====================>
import UIKit
import CoreData
class ViewController-1: UIViewController,UITableViewDelegate,UITableViewDataSource
{
#IBOutlet var table_view: UITableView!
var my_data_array = NSMutableArray()
var data_array = NSMutableArray()
var data_fet:[NSManagedObject] = []
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewWillAppear(_ animated: Bool)
{
let app = UIApplication.shared.delegate as! AppDelegate
let context_view = app.persistentContainer.viewContext
let fetch_data = NSFetchRequest<NSManagedObject>(entityName: "Student_detail")
do
{
//
data_array = try context_view.fetch(fetch_data as! NSFetchRequest<NSFetchRequestResult>) as! NSMutableArray
print("this is array",data_array)
}
catch let error as NSError
{
print(error)
}
table_view.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int
{
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return data_array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let t_cell = tableView.dequeueReusableCell(withIdentifier: "cell_data", for: indexPath) as! TableViewCell_data_view
let result_data = data_array[indexPath.row]
t_cell.t_std_name.text = (result_data as AnyObject).value(forKey: "stdName") as? String
t_cell.t_roll_no.text = (result_data as AnyObject).value(forKey: "stdRoll") as? String
t_cell.t_std_dept.text = (result_data as AnyObject).value(forKey: "stdDept") as? String
t_cell.t_grade.text = (result_data as AnyObject).value(forKey: "stdGrade") as? String
t_cell.t_img_view.image = UIImage(data: (result_data as AnyObject).value(forKey: "stdImage") as! Data)
return t_cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
performSegue(withIdentifier: "data_passing", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == "data_passing"
{
let view_c = segue.destination as! ViewController_Register
let index_path = table_view.indexPathForSelectedRow
let update_std_result = self.data_array[(index_path?.row)!]
view_c.data_result = update_std_result as! NSManagedObject
}
}
VIEWCONTROLLER--2:
=====================>
import UIKit
import CoreData
class ViewController_Register: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate
{
#IBOutlet var std_name: UITextField!
#IBOutlet var std_roll: UITextField!
#IBOutlet var std_dept: UITextField!
#IBOutlet var std_grade: UITextField!
#IBOutlet var std_image: UIImageView!
var data_result:NSManagedObject!
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view.
std_image.isUserInteractionEnabled = true
if data_result != nil
{
std_name.text = data_result.value(forKey: "stdName") as? String
std_roll.text = data_result.value(forKey: "stdRoll") as? String
std_dept.text = data_result.value(forKey: "stdDept") as? String
std_grade.text = data_result.value(forKey: "stdGrade") as? String
std_image.image = UIImage(data: data_result.value(forKey: "stdImage") as! Data)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func image_action(_ sender: UITapGestureRecognizer)
{
let img_pick = UIImagePickerController()
img_pick.delegate = self
img_pick.allowsEditing = true
img_pick.sourceType = UIImagePickerControllerSourceType.photoLibrary
self.present(img_pick, animated: true)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
{
if let img_delegate = info[UIImagePickerControllerOriginalImage] as? UIImage
{
std_image.image = img_delegate
}
else
{
print("Error")
}
self.dismiss(animated: true, completion: nil)
}
#IBAction func register_action(_ sender: Any)
{
let app = UIApplication.shared.delegate as! AppDelegate
let context_view = app.persistentContainer.viewContext
if data_result != nil
{
data_result.setValue(std_name.text, forKey: "stdName")
data_result.setValue(std_roll.text, forKey: "stdRoll")
data_result.setValue(std_dept.text, forKey: "stdDept")
data_result.setValue(std_grade.text, forKey: "stdGrade")
let img_data = UIImageJPEGRepresentation(std_image.image!, 1.0)!
data_result.setValue(img_data, forKey: "stdImage")
}
else
{
let student = NSEntityDescription.insertNewObject(forEntityName: "Student_detail", into: context_view) as NSManagedObject
student.setValue(std_name.text, forKey: "stdName")
student.setValue(std_roll.text, forKey: "stdRoll")
student.setValue(std_dept.text, forKey: "stdDept")
student.setValue(std_grade.text, forKey: "stdGrade")
let img_data = UIImageJPEGRepresentation(std_image.image!, 1.0)!
student.setValue(img_data, forKey: "stdImage")
do
{
try context_view.save()
print("name is-->",std_name.text!,"roll no is-->",std_roll.text!,"dept is -->",std_dept.text!)
}
catch let error as NSError
{
print(error.localizedDescription)
}
}
self.navigationController?.popViewController(animated: true)
}
}

managedObjectModel Bad Instruction when show image in tableview

I'm new in using swift and I have a problem to show image in my custom tableview. I take a code from here
this is my coredata
lazy var managedObjectModel: NSManagedObjectModel = {
let modelURL = NSBundle.mainBundle().URLForResource("test", withExtension: "momd")! <---- The error in here
return NSManagedObjectModel(contentsOfURL: modelURL)!
}()
this is my code in controller
func extract_json(jsonData:NSData) {
let json: AnyObject?
do {
json = try NSJSONSerialization.JSONObjectWithData(jsonData, options: [])
} catch {
json = nil
return
}
if let list = json as? NSArray {
for (var i = 0; i < list.count ; i++ ) {
if let data_block = list[i] as? NSDictionary {
TableData.append(datastruct(add: data_block))
}
}
do {
try read()
} catch {}
do_table_refresh()
}
}
func do_table_refresh() {
dispatch_async(dispatch_get_main_queue(), {
self.tableview.reloadData()
//self.activityView.hidden = true
return
})
}
func load_image(urlString:String, imageview:UIImageView, index:NSInteger) {
let url:NSURL = NSURL(string: urlString)!
let session = NSURLSession.sharedSession()
let task = session.downloadTaskWithURL(url) {
(
let location, let response, let error) in
guard let _:NSURL = location, let _:NSURLResponse = response where error == nil else {
print("error")
return
}
let imageData = NSData(contentsOfURL: location!)
dispatch_async(dispatch_get_main_queue(), {
self.TableData[index].image = UIImage(data: imageData!)
self.save(index,image: self.TableData[index].image!)
imageview.image = self.TableData[index].image
return
})
}
task.resume()
}
func read() throws {
do {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Images")
let fetchedResults = try managedContext!.executeFetchRequest(fetchRequest)
for (var i=0; i < fetchedResults.count; i++) {
let single_result = fetchedResults[i]
let index = single_result.valueForKey("index") as! NSInteger
let img: NSData? = single_result.valueForKey("image") as? NSData
TableData[index].image = UIImage(data: img!)
}
} catch {
print("error")
throw ErrorHandler.ErrorFetchingResults
}
}
func save(id:Int,image:UIImage) {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
let entity = NSEntityDescription.entityForName("Images",
inManagedObjectContext: managedContext)
let options = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext:managedContext)
let newImageData = UIImageJPEGRepresentation(image,1)
options.setValue(id, forKey: "index")
options.setValue(newImageData, forKey: "image")
do {
try managedContext.save()
} catch {
print("error")
}
}
in they example it run smoothly but when I try to code it in my project there is an error. It said as
EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
and I can't find any way to fix it.
Please give me some hint how to fix this problem
Thanks, for all the help
I have found my own solution for my problem
The solution is that CoreData I create is xcdatamodel not xcdatamodeld and in my AppDelegate I use momd so I just create a datamodel with xcdatamodeld extension

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

I'm not sure what I'm doing wrong here, but when I save the first time into coredata, it works just fine. When I try to overwrite that, it doesn't.
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")
*/
Load Login Data Func
the function that calls on saveLogin data
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
}
}
Since batchupdate is more useful in larger chunks of data, I think this is a more subtle approach.
func saveLoginData(accessToken: String, userName: String) {
var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
var context: NSManagedObjectContext = appDel.managedObjectContext!
var fetchRequest = NSFetchRequest<NSFetchRequestResult>(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)
}
}
}
I tried to translate it a bit to your situation if I'm not mistaken, but have not tested it.
fetchRequest.predicate basically sets the filter on the attribute userName from the entity LoginData, with the (user)name you enter when calling the function. Assuming in this example you have only one username with the same name. Then it does a fetchrequest with the given filter, so you can change it's value with setValue with the accesToken you also enter when calling the function. The code after: if fetchResults.count != 0 , only executes when the username exists.
Swift 5
You can create a method that can work to both, include and update.
Assuming you have an entity created on CoreData with the name Users:
var context: NSManagedObjectContext {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}
let user: Users!
let fetchUser: NSFetchRequest<Users> = Users.fetchRequest()
fetchUser.predicate = NSPredicate(format: "id = %#", id as String)
let results = try? context.fetch(fetchUser)
if results?.count == 0 {
// here you are inserting
user = Users(context: context)
} else {
// here you are updating
user = results?.first
}
user.id = id
user.name = name
...
try context.save()
Updated for Swift 4 & XCode 9.2
To answer your question...
How do you update a CoreData entry that has already been saved in Swift?
You first need to get a reference to your AppDelegate and viewContext. You then need to set up a NSFetchRequest for the Entity you are looking to update, in my example that would be "Alert". You then set up your fetch to find the result you are looking for. In the example, my result found Alerts by their creation date and alert type.
To further read how to query using a predicate.
Stack Overflow Example &
Apple Documentation
I then context.fetch(fetchRequest), set the results to the value I wanted to update, and dealt with errors in a try catch.
Finally 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)")
}
Swift >= 2 the method now returns a non-optional and throws an error in the error case, which must be handled with try-catch:
let context = self.fetchedResultsController.managedObjectContext
let entity = self.fetchedResultsController.fetchRequest.entity!
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entity.name!)
fetchRequest.predicate = NSPredicate(format: "notificationId = 13")
do {
let list = try context.executeFetchRequest(fetchRequest) as? [NSManagedObject]
// Check notificationId available then not save
if list!.count == 0 {
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)")
}
You're creating multiple new LoginData objects, but your loadLoginData method is always returning the same object, the first one from the fetch request results.
You want to keep updating the same object, so you need to change your saveLoginDetails method.
Instead of creating a new object (which is what insertNewObjectForEntityName) does, use the loadLoginDetails method to get your existing one, and change the property on there.
It worked for me you should try this:
let managedContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Students", in: managedContext)
let request = NSFetchRequest<NSFetchRequestResult>()
request.entity = entity
let predicate = NSPredicate(format: "(name = %#)", txtName.text!)
request.predicate = predicate
do {
var results =
try managedContext.fetch(request)
let objectUpdate = results[0] as! NSManagedObject
objectUpdate.setValue(txtName.text!, forKey: "name")
objectUpdate.setValue(txtPhone.text!, forKey: "phone")
objectUpdate.setValue(txt_Address.text!, forKey: "address")
do {
try managedContext.save()
txtName.text = ""
txtPhone.text = ""
txt_Address.text = ""
labelStatus.text = "Updated"
}catch let error as NSError {
labelStatus.text = error.localizedFailureReason
}
}
catch let error as NSError {
labelStatus.text = error.localizedFailureReason
}
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")
}
good luck
Swift 4,5
Common Function for all Enetities
func updateEntityObjectByKeyValue<T>(className: T.Type, key: String, value: Any, columns: [String: Any]) -> Bool {
guard columns.keys.count != 0 else {
return false
}
let context = CoreDataStack.sharedStack.mainContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: String(describing: className.self))
//Depends on data type.Added fetchRequest using Int and string
if let sValue = value as? String {
let predicate = NSPredicate(format: "\(key) == %#", sValue)
fetchRequest.predicate = predicate
} else if let iValue = value as? Int {
let predicate = NSPredicate(format: "\(key) == %d", iValue)
fetchRequest.predicate = predicate
}
do {
let result = try context.fetch(fetchRequest)
if result.count != 0 {
if let managedObject = result[0] as? NSManagedObject {
for (key, value) in columns {
managedObject.setValue(value, forKey: key)
}
do {
CoreDataStack.sharedStack.saveMainContext()
return true
}
catch let error {
print(error.localizedDescription)
}
}
}
return false
} catch let error {
print(error.localizedDescription)
}
return false
}
How to use:
let employeeId = your id
let isSaved = self.updateEntityObjectByKeyValue(className: EmployeeData.self, key: "id", value: employeeId, columns: ["status" :1])
if isSaved {
print("Saved")
}
Step:1 - create new project and select "Use Core Data"
go through : "https://medium.com/#ankurvekariya/core-data-crud-with-swift-4-2-for-beginners-40efe4e7d1cc"
Step:2 - Inside ViewController (userList)
import UIKit
import CoreData
class ViewController: UIViewController, UITableViewDelegate , UITableViewDataSource {
var arrUser = Array<Any>()
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.title = "User List"
self.tableView.separatorStyle = .none
self.retrieveData(Delete: false, indexpath: 0)
let logoutBarButtonItem = UIBarButtonItem(image: UIImage(named: "addImage"), style: .done, target: self, action: #selector(addNewUser))
self.navigationItem.rightBarButtonItem = logoutBarButtonItem
}
override func viewDidAppear(_ animated: Bool)
{
super.viewDidDisappear(animated)
self.retrieveData(Delete: false, indexpath: 0)
}
#objc func addNewUser(){
let userVC = self.storyboard?.instantiateViewController(withIdentifier: "AddUser_VC") as! AddUser_VC
self.navigationController?.pushViewController(userVC, animated: true)
}
//MARK: - TableView DataSource Delegate
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.arrUser.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "UserCell") as! UserCell
cell.selectionStyle = .none
let dictData = self.arrUser[indexPath.row] as? NSManagedObject
cell.lblName.text = dictData?.value(forKey: "name") as? String ?? ""
cell.lblPost.text = dictData?.value(forKey: "post") as? String ?? ""
cell.lblEmail.text = dictData?.value(forKey: "email") as? String ?? ""
cell.lblPhone.text = String(dictData?.value(forKey: "phone") as? Int ?? 0)
cell.imageData?.image = UIImage(data: dictData?.value(forKey: "image") as? Data ?? Data())
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 140
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let dictData = self.arrUser[indexPath.row] as? NSManagedObject
let AddUserVC = self.storyboard?.instantiateViewController(withIdentifier: "AddUser_VC") as! AddUser_VC
AddUserVC.isEdit = true
AddUserVC.dictObj = dictData
self.navigationController?.pushViewController(AddUserVC, animated: true)
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if (editingStyle == .delete) {
//self.deleteData(indexpath: indexPath.row)
self.retrieveData(Delete: true, indexpath: indexPath.row)
}
}
//MARK: - retrieveData
func retrieveData(Delete:Bool , indexpath:Int) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "UserTable")
if (Delete == true)
{
do
{
let test = try managedContext.fetch(fetchRequest)
let objectToDelete = test[indexpath] as! NSManagedObject
managedContext.delete(objectToDelete)
do{
try managedContext.save()
self.retrieveData(Delete: false, indexpath: 0)
}
catch
{
print(error)
}
}
catch
{
print(error)
}
}
do {
self.arrUser = try managedContext.fetch(fetchRequest)
self.tableView.reloadData()
print(self.arrUser)
} catch {
print("Failed")
}
}
}
Step:3 - Inside UserCell
import UIKit
class UserCell: UITableViewCell {
#IBOutlet var lblName: UILabel!
#IBOutlet var lblEmail: UILabel!
#IBOutlet var lblPost: UILabel!
#IBOutlet var lblPhone: UILabel!
#IBOutlet var imageData: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
self.imageData.layer.cornerRadius = self.imageData.frame.height / 2
self.imageData.layer.borderWidth = 1.0
self.imageData.layer.borderColor = UIColor.lightGray.cgColor
self.imageData.layer.masksToBounds = true
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Step:4 - Inside AddUserVC
import UIKit
import CoreData
class AddUser_VC: UIViewController ,UIImagePickerControllerDelegate ,UINavigationControllerDelegate {
var dictObj: NSManagedObject!
var isEdit:Bool = false
#IBOutlet var imageData: UIImageView!
#IBOutlet var txtName: UITextField!
#IBOutlet var txtEmail: UITextField!
#IBOutlet var txtPost: UITextField!
#IBOutlet var txtPhone: UITextField!
#IBOutlet var btnAddUser: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
self.imageData.layer.cornerRadius = self.imageData.frame.height / 2
self.imageData.layer.borderWidth = 1.0
self.imageData.layer.borderColor = UIColor.lightGray.cgColor
self.imageData.layer.masksToBounds = true
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
self.imageData.isUserInteractionEnabled = true
self.imageData.addGestureRecognizer(tapGestureRecognizer)
if (self.isEdit == true)
{
self.txtName.text = dictObj.value(forKey: "name") as? String ?? ""
self.txtEmail.text = dictObj.value(forKey: "email") as? String ?? ""
self.txtPost.text = dictObj.value(forKey: "post") as? String ?? ""
self.txtPhone.text = String(dictObj.value(forKey: "phone") as? Int ?? 0)
self.imageData?.image = UIImage(data: dictObj?.value(forKey: "image") as? Data ?? Data())
self.btnAddUser.setTitle("UPDATE", for: .normal)
}
}
//MARK: - btnAddUserAction Method -
#IBAction func btnAddUserAction(_ sender: Any) {
let arrData = [self.txtName,self.txtEmail,self.txtPost,self.txtPhone]
for txt in arrData
{
if (txt?.text == "")
{
let alert = UIAlertController(title: "Alert", message: "Please Enter All Fields", preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "Click", style: UIAlertAction.Style.default, handler: nil))
self.present(alert, animated: true, completion: nil)
return
}
}
self.createData()
}
//MARK: - Image Tap Method -
#objc func imageTapped(tapGestureRecognizer: UITapGestureRecognizer)
{
let alert = UIAlertController(title: "Choose Image", message: nil, preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: { _ in
self.openCamera()
}))
alert.addAction(UIAlertAction(title: "Gallery", style: .default, handler: { _ in
self.openGallery()
}))
alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
func openCamera()
{
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.camera) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerController.SourceType.camera
imagePicker.allowsEditing = false
self.present(imagePicker, animated: true, completion: nil)
}
else
{
let alert = UIAlertController(title: "Warning", message: "You don't have camera", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
func openGallery()
{
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.photoLibrary){
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.allowsEditing = true
imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary
self.present(imagePicker, animated: true, completion: nil)
}
else
{
let alert = UIAlertController(title: "Warning", message: "You don't have permission to access gallery.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard (info[.originalImage] as? UIImage) != nil else {
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
}
self.imageData.image = info[.originalImage] as? UIImage
picker.dismiss(animated: true, completion: nil)
}
//MARK: - createData
func createData(){
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let userEntity = NSEntityDescription.entity(forEntityName: "UserTable", in: managedContext)!
var user = NSManagedObject()
if(isEdit == true)
{
user = self.dictObj
}
else
{
user = NSManagedObject(entity: userEntity, insertInto: managedContext)
}
let image = self.imageData.image!.jpegData(compressionQuality: 0.5)as NSData?
user.setValue(self.txtName.text, forKeyPath: "name")
user.setValue(self.txtEmail.text, forKey: "email")
user.setValue(self.txtPost.text, forKey: "post")
user.setValue(Int(self.txtPhone.text!), forKey: "phone")
user.setValue(image, forKey: "image")
do {
try managedContext.save()
self.navigationController?.popViewController(animated: true)
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
}
Alternate Methods:
//MARK: - CoreData Methods -
func createData(){
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let userEntity = NSEntityDescription.entity(forEntityName: "Movie", in: managedContext)!
for obj in self.MoviewList.arrMovieData{
let user = NSManagedObject(entity: userEntity, insertInto: managedContext)
user.setValue(obj.id, forKey: "id")
user.setValue(obj.title, forKey: "title")
user.setValue(obj.overview, forKey: "overview")
let url = API.IMAGE_BASE_URL + obj.poster_path
user.setValue(url, forKey: "poster_path")
}
do {
try managedContext.save()
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
func retrieveData() {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Movie")
do {
let result = try managedContext.fetch(fetchRequest)
var arr = [[String:AnyObject]]()
for data in result as! [NSManagedObject] {
var obj = [String:AnyObject]()
obj["id"] = data.value(forKey: "id") as AnyObject
obj["title"] = data.value(forKey: "title") as AnyObject
obj["overview"] = data.value(forKey: "overview") as AnyObject
obj["poster_path"] = data.value(forKey: "poster_path") as AnyObject
arr.append(obj)
}
self.MoviewList = MovieDataList(data: arr)
self.tableView.reloadData()
} catch {
print("Failed")
}
}
func deleteAllRecords() {
let delegate = UIApplication.shared.delegate as! AppDelegate
let context = delegate.persistentContainer.viewContext
let deleteFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Movie")
let deleteRequest = NSBatchDeleteRequest(fetchRequest: deleteFetch)
do {
try context.execute(deleteRequest)
try context.save()
self.createData()
} catch {
}
}
//For Swift UI inside the view outside the body :)
#Environment(.managedObjectContext) var managedObjectContext
var isNewRecord = false
let aNewContact: Contact!
let fetchContact: NSFetchRequest<Contact> = Contact.fetchRequest() as! NSFetchRequest<Contact>
fetchContact.predicate = NSPredicate(format: "record_id == %#", contactRemoteModel.contacts[i].record_id as CVarArg)
let results = try? managedObjectContext.fetch(fetchContact)
if results?.count == 0 {
// here you are inserting
aNewContact = Contact(context: managedObjectContext)
aNewContact.id = UUID()
isNewRecord = true
print("Insert")
} else {
// here you are updating
aNewContact = results?.first
print("UpDate")
}
It worked for me, you should try this:
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return}
let managedContext = appDelegate.persistentContainer.viewContext
// if object nil is checked if new entity will be created or created one will be updated
if object == nil {
// create new entity:
let entityObj = NSEntityDescription.entity(forEntityName: "EntityName", in: managedContext)!
let entity = NSManagedObject(entity: entityObj, insertInto: managedContext)
entity("new value", forKeyPath: "entityValue")
do {
try managedContext.save()
entities.append(entity)
self.navigationController?.popViewController(animated: true)
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
else {
// the created entity will be updated selected object is entity -> came from previous view controller:
self.entity?.setValue("updated value", forKey: "entityValue")
do {
try managedContext.save()
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
self.navigationController?.popViewController(animated: true)
}
This worked for me. First i set filter by given attribute "taskName" with fetchRequest.predicate. Then i fetch data that already been saved and set value for "status" to update that object.
func updateTaskStatus(status: Bool){
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest: NSFetchRequest<Task> = Task.fetchRequest()
let predicate = NSPredicate(format: "(taskName = %#)", (task?.taskName)!)
fetchRequest.predicate = predicate
do {
let result = try managedContext.fetch(fetchRequest)
task = result[0] as NSManagedObject as? Task
task?.setValue(status, forKey: "status")
do {
try managedContext.save()
}catch let error as NSError {
print("\(error)")
}
}catch let error as NSError {
print("\(error)")
}
}
#Update Data in #CoreData #iOS #swift
Simply follow below steps to update data in CoreData which you already saved
#Step1 :- refer to persistent container & create object of viewContext
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let viewContext = appDelegate.persistentContainer.viewContext
#Step2 :- create FetchRequest
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "User") // here User is entity name
//Step3 :- add predicate to fetch request by passing attribute and value
fetchRequest.predicate = NSPredicate(formate: "userName = %#","XYZ")
//Step4 :- fetch record using viewContext by passing fetchRequest and set new value in it
do {
let results = try viewContext.fetch(fetchRequest) as? [NSManagedObject]
if result?.count !=0 {
result?[0].setValue("ABC",forKey: "userName")
}
} catch {
print("failed to fetch record from CoreData")
}
//Step5 :- finally call save method of viewcontext so new value get reflect in CoreData
do {
viewContext.save()
} catch {}
Note :- in predicate the value "XYZ" can be value of attribute and format will contain name of attribute such like username , age password ....etc , in result?[0].setValue you can set new value for particular attribute by passing value and keynote , you can skip step5 and can execute save method inside step4 after Line where we setting new value
There's a new feature called Batch Updates.
I think this article will help you:
http://www.bignerdranch.com/blog/new-in-core-data-and-ios-8-batch-updating/
Basicly what you do is use the NSBatchUpdateRequest instead of NSFetchRequest, filter the results with NSPredicate, change the value in the results, and save the data.
Another tutorial in swift:
http://code.tutsplus.com/tutorials/ios-8-core-data-and-batch-updates--cms-22164
In swift 4 or swift 5, you can used like bellow
func update(accessToken:String,username:String){
//1
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
//2
let fetchRequest =
NSFetchRequest<NSManagedObject>(entityName: "LoginData")
// 3
let predicate = NSPredicate(format: "%K == %#", "username", username)
fetchRequest.predicate = predicate
//3
do {
let rs = try managedContext.fetch(fetchRequest)
for result in rs as [NSManagedObject] {
// update
do {
var managedObject = rs[0]
managedObject.setValue(accessToken, forKey: "accessToken")
try managedContext.save()
print("update successfull")
} catch let error as NSError {
print("Could not Update. \(error), \(error.userInfo)")
}
//end update
}
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}

Resources