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

后端 未结 14 2721
有刺的猬
有刺的猬 2020-11-30 00:55

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 t         


        
14条回答
  •  误落风尘
    2020-11-30 01:39

    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()
    @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(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(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(entityName: "Movie")
        let deleteRequest = NSBatchDeleteRequest(fetchRequest: deleteFetch)
    
        do {
            try context.execute(deleteRequest)
            try context.save()
            self.createData()
        } catch {
    
        }
    }
    

提交回复
热议问题