如何使用 Swift 删除 coredata 中的特定记录?

Posted

技术标签:

【中文标题】如何使用 Swift 删除 coredata 中的特定记录?【英文标题】:how to delete particular record in coredata using Swift? 【发布时间】:2020-01-07 09:49:26 【问题描述】:

我的场景是,我将 JSON 数据加载到 CoreData 中,然后我将其提取到 Tableview 中。现在,每个表格视图单元格都可以使用DeleteEdit 按钮进行滑动。如果我点击删除,我需要从 coredata 和 tableview 这两个地方删除数据。

我的 JSON 结构

   class displyDataClass 
    var name : String
    var username : String
    var email : String

init(name : String,username : String,email :String) 
    self.name = name
    self.username = username
    self.email = email
   

JSON 加载到 CoreData

import UIKit
import CoreData

class ViewController: UIViewController ,UITableViewDelegate,UITableViewDataSource

var displayDatasssss = [displyDataClass]()
var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

@IBOutlet weak var tableView: UITableView!

override func viewDidLoad() 
    super.viewDidLoad()
    print("hai")

    // 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.

func numberOfSections(in tableView: UITableView) -> Int 
    return 1

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return displayDatasssss.count

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell1") as! TableViewCell1





    let request = NSFetchRequest<NSFetchRequestResult>(entityName: "User")
    cell.label.text = displayDatasssss[indexPath.row].email


    let _:AppDelegate = (UIApplication.shared.delegate as! AppDelegate)
    let context:NSManagedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    let newUser = NSEntityDescription.insertNewObject(forEntityName: "User", into: context) as NSManagedObject
    newUser.setValue(cell.label.text, forKey: "name")

    do 
        try context.save()
     catch 
    print(newUser)
    print("Object Saved.")


    let myStringValue = cell.label.text
    request.predicate = NSPredicate (format: "name == %@", myStringValue!)
    do
    
        let result = try context.fetch(request)
        if result.count > 0
        
            let nameData = (result[0] as AnyObject).value(forKey: "name") as! String
            print(nameData)

        
    
    catch 
        //handle error
        print(error)
    

    return cell


@IBAction func tap(_ sender: Any) 
    let url = "http://jsonplaceholder.typicode.com/users"
    var request = URLRequest(url: URL(string: url)!)
    request.httpMethod = "GET"
    let configuration = URLSessionConfiguration.default
    let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: OperationQueue.main)
    let task = session.dataTask(with: request)(data, response,error)in
        if (error != nil)
            print("Error")
        
        else
            do
                // Array of Data
                let fetchData = try JSONSerialization.jsonObject(with: data!, options: .mutableLeaves) as! NSArray

                for eachData in fetchData 

                    let eachdataitem = eachData as! [String : Any]
                    let name = eachdataitem["name"]as! String
                    let username = eachdataitem["username"]as! String

                    let email = eachdataitem["email"]as! String
                    self.displayDatasssss.append(displyDataClass(name: name, username: username,email : email))
                
                self.tableView.reloadData()
            
            catch
                print("Error 2")
            

        
    
    task.resume()

    




class displyDataClass 
    var name : String
    var username : String
    var email : String

init(name : String,username : String,email :String) 
    self.name = name
    self.username = username
    self.email = email
   

以下代码用于删除

// delete action two
        let deleteAction = UITableViewRowAction(style: .default, title: "Delete", handler:  (action, indexPath) in
            print("Delete tapped")

            // remove the deleted item from the model
            let appDel:AppDelegate = UIApplication.shared.delegate as! AppDelegate
            let managedObjectContext = appDel.persistentContainer.viewContext
            managedObjectContext.delete(self.displayDatasssssindexPath.row])
            self.milestoneTitles.remove(at: indexPath.row)
            do 
                try managedObjectContext.save()
             catch _ 
            

            self.tableView.deleteRows(at: [indexPath], with: .automatic)
           return [editAction, deleteAction]
       

【问题讨论】:

请更准确地解释您的问题。 @dahiya_boy 我在managedObjectContext.delete(self.displayDatasssssindexPath.row])收到错误Cannot convert value of type 'displyDataClass' to expected argument type 'NSManagedObject' 如果您是 ios 新手或对核心数据了解较少,我建议您参考此 -> code.tutsplus.com/tutorials/… ,会有更多帖子可用。之后,如果您仍有任何问题,我们很乐意为您提供帮助。 目前,错误是说displyDataClass 不是NSManageObjectNSManageObject 是您在架构中创建实体的对象。 Xcode 在内部管理NSManageObject,您只需要对该对象进行查询。还有一个提示,在从 tableView 中删除单元格时,您需要先删除数据源。 reference @dahiya_boy 我将 JSON 数据存储到 displayDatasssss = [displyDataClass]() 并将值存储到 coredata 现在如何使用 Swift 从 coredata 中删除特定数据 【参考方案1】:

不要使用自定义类。仅使用提供的 User 类。

首先声明一个数据源数组(替换displayDatasssss

var users = [User]()

tap 方法中加载数据并在核心数据堆栈中插入新项目。考虑每次点击按钮都会将重复的项目插入数据库。旧条目不会被删除。

因为User 只有nameid 属性,所以email 被分配给id

项目被附加到数据源数组并保存在上下文中。

@IBAction func tap(_ sender: Any) 
    let url = "http://jsonplaceholder.typicode.com/users")!
    let task = session.dataTask(with: url) [unowned self] (data, response,error)in
        if let error = error  print(error); return 
        do 
            // Array of Data
            let fetchData = try JSONSerialization.jsonObject(with: data!) as! [[String:Any]]    
            for eachDataItem in fetchData                    
                let name = eachdataitem["name"] as! String
                let email = eachdataitem["email"] as! String
                let newUser = User(context: self.context)
                newUser.name = name
                newUser.id = email
                self.users.append(newUser)
            
            DispatchQueue.main.async 
               self.tableView.reloadData()
            
            try self.context.save()
        catch
           print("Error 2", error)
       
    
    task.resume()

viewDidLoad 中从CoreData 获取数据并重新加载表格视图

override func viewDidLoad() 
    super.viewDidLoad()
    do 
       let request : NSFetchRequest<User> = User.fetchRequest()
       users = try context.fetch(request)
       tableView.reloadData()
     catch  print(error) 

cellForRow 中将属性值分配给标签,仅此而已

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell1") as! TableViewCell1 
    let user = users[indexPath.row]
    cell.label.text = user.name  
    return cell

delete方法和你的很像

let deleteAction = UITableViewRowAction(style: .default, title: "Delete", handler:  [unowned self] (action, indexPath) in
    print("Delete tapped")

    // remove the deleted item from the model
    let objectToDelete = self.users.remove(at: indexPath.row)
    self.context.delete(objectToDelete)
    do 
        try self.context.save()
        self.tableView.deleteRows(at: [indexPath], with: .automatic)
     catch 
       print(error)
    

return [editAction, deleteAction]

注意:总是打印错误,不要忽略它们或只打印无意义的文字字符串

【讨论】:

你是一位伟大的程序员大师。惊人的。我很想向你学习。 :) 而不是JSONSerialization 如果我使用JSONDecoder 那么如何附加值let result = try JSONDecoder().decode(User.self, from:data) let status = result.status if status == true let item = result.data let newUser = User(context: self.context) newUser.id = ?? newUser.milestone = ?? 要将 JSON 直接解码为 User,您必须在类中采用 Decodable。这不是微不足道的,另一个问题。无论如何,JSON 中没有密钥 status。根对象是用户数组。 我有点困惑。我所做的一切。但是let result = try JSONDecoder().decode(User, from:data) 如果我这样做会显示错误。如何更新这个let result = try JSONDecoder().decode(User.self, from:data) let status = result.status if status == true let item = result.data let newUser = User(context: self.context) newUser.id = newUser.name = self.users.append(newUser) 这段代码不能工作有 3 个原因:#1) User 不符合 Decodable, #2) 如果它确实解码的对象实际上是 [User].self 和 #3) 一次同样在给定 URL 的 JSON 中没有键 status

以上是关于如何使用 Swift 删除 coredata 中的特定记录?的主要内容,如果未能解决你的问题,请参考以下文章

Swift - 删除CoreData行[重复]

如何在 Swift 中从 Core Data 中删除数据时删除 UITableView 行?

SWIFT - Coredata删除关系记录

使用Swift 3和CoreData删除表视图行

如何使用 Swift3 访问 CoreData 中的数据索引

删除核心数据对象时,如何在 Swift 5 中同时删除其所有相关对象?