【问题标题】:query with Fetch Request using CoreData on Swift在 Swift 上使用 CoreData 使用 Fetch Request 进行查询
【发布时间】:2020-07-31 08:28:38
【问题描述】:

对不起,如果已经有一个关于它的线程但被卡住了一段时间。

我对 CoreData 有点陌生(只知道如何持久化和获取项目),我正在尝试在我的应用程序中进行一个小查询,该查询将仅加载具有 isDone 属性 =“True”的那些。

问题是我不知道如何使用 NSFetchRequest 和 NSPredicate 所以我有点卡住了,希望你们能帮助我一些提示

import Foundation
import CoreData
import UIKit
import SwipeCellKit

class TasksManViewController: UITableViewController, SwipeTableViewCellDelegate {
    
    
    
    @IBOutlet weak var Sege: UISegmentedControl!
    
    let isSwipeRightEnabled = true
    
    
    var tasksArray = [Task](){
        didSet {
            // because we perform this operation on the main thread, it is safe
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }
        }
    }
    
    var doneTasksArr = [Task]() // an array of what to disply.
    
    
    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    
    
    override func viewDidLoad() {
        
    }
    
    
    override func viewWillAppear(_ animated: Bool) {
        loadTasks()
    }

    
    
    // MARK: - DataSource + Delegate Methods:
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return tasksArray.count
    }
    
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "taskCellRow") as! SwipeTableViewCell
        cell.delegate = self
        
        cell.textLabel?.text = tasksArray[indexPath.row].title
        
        return cell
    }
    
    
    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
        if orientation == .left {
            guard isSwipeRightEnabled else { return nil }
            let doneAction = SwipeAction(style: .destructive, title: "Done") { (action, indexPath) in
                
                //STEP1: Append the task to the doneTasksArr:
                self.tasksArray[indexPath.row].isDone = true
                self.doneTasksArr.append(self.tasksArray[indexPath.row])
                
                
                //STEP2: Delete the task from the tasksArray since it was done.
                self.context.delete(self.tasksArray[indexPath.row])
                
                //STEP3: Remove the Row:
                self.tasksArray.remove(at: indexPath.row)
                
                //STEP4: Update the Model:
                self.saveTasks()
                
                

                self.tableView.reloadData()

                
                
                
            }
            
            
            //configure btn:
            doneAction.backgroundColor = .cyan
            
            return [doneAction]
            
        } else {
            let deleteAction = SwipeAction(style: .destructive, title: "Delete") { action, indexPath in
                
                self.context.delete(self.tasksArray[indexPath.row])
                
                self.tasksArray.remove(at: indexPath.row)
                
                
                self.saveTasks()
                
                self.tableView.reloadData()
                
            }
            
            return [deleteAction]
        }
        
    }
    
    
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        
        
    }
    
    // MARK: - Class Methods:
    @IBAction func addBtnTapped(_ sender: UIBarButtonItem) {
        
        insertNewTask()
        
    }
    
    
    
    func insertNewTask() {
        var textField = UITextField()
        
        
        let alert = UIAlertController(title: "New Task", message: "Please Add Your Task", preferredStyle: .alert)
        
        alert.addTextField { (alertTextField) in
            alertTextField.placeholder = "Create New Task"
            textField = alertTextField
        }
        
        
        let action = UIAlertAction(title: "Add", style: .default) { (action) in
            let newItem = Task(context: self.context)
            
            newItem.title = textField.text!
            newItem.isDone = false
            
            
            self.tasksArray.append(newItem)

            self.saveTasks()
            
            self.tableView.reloadData()

        }
        
        
        
        alert.addAction(action)
        
        
        
        self.present(alert, animated: true, completion: nil)
        
    }
    
    
    
    // MARK: - Sege Section:
    @IBAction func segeControlTapped(_ sender: UISegmentedControl) {
        
        switch Sege.selectedSegmentIndex
        {
        case 0:
            //Loading normal tasks which not done
            loadTasks()
            
        case 1:
            //Loading the doneTasks:
            loadDoneTasksFrom()

            
        default:
            print("There's something wrong with Sege!")
        }
        
        tableView.reloadData()
    }
    
    
    //MARK: - Model Manipulation Methods:
    func saveTasks() {
        do {
            try! context.save()
        } catch {
            print("Error Saving context \(error)")
        }
    }
    
    func loadTasks() {
        let request: NSFetchRequest<Task> = Task.fetchRequest()
        do{
            tasksArray = try! context.fetch(request)
        } catch {
            print("There was an error with loading items \(error)")
        }
    }
    
    
    
    func loadDoneTasksFrom() {
        let request: NSFetchRequest<Task> = Task.fetchRequest()
        
        request.predicate = NSPredicate(format: "isDone == %@", "true")
        
        request.sortDescriptors = [NSSortDescriptor(key: "isDone", ascending: false)]
        
        do{
            tasksArray = try context.fetch(request)
        } catch {
            print("Error fetching data from context\(error)")
        }
        
        tableView.reloadData()
        
    }
    
    
    
    
}
    
    
    

【问题讨论】:

    标签: ios swift core-data


    【解决方案1】:

    您可以使用其中一种

    NSPredicate(format: "isDone == %@", NSNumber(value: true))
    NSPredicate(format: "isDone = %d", true)
    

    【讨论】:

    • 你的意思是在我的方法中使用它?
    【解决方案2】:

    你可以这样写查询

    static func getDoneTasks() -> NSFetchRequest<Task> {
            let request:NSFetchRequest<Task> = Task.fetchRequest() as! NSFetchRequest<Task>
    
            let sortDescriptor = NSSortDescriptor(key: "createdAt", ascending: false)
    
            request.sortDescriptors = [sortDescriptor]
            let isDone = true
            request.predicate = NSPredicate(format: "isDone == %@", isDone)
            return request
        }
    

    然后您只需使用以下命令获取它们:

    @FetchRequest(fetchRequest: Task.getDoneTasks()) var doneTasks: FetchedResults<Task>
    

    您还可以在函数中添加参数等并将它们传递到FetchRequest

    可以推荐this教程了解coredata的核心概念

    【讨论】:

    • 出于某种原因,它说“模糊使用 'fetchRequest()'”
    • 一旦我实现了这个方法:|顺便说一句,@FetchRequest 据我所知适用于 SwiftUI
    • 谢谢你,我一直在努力解决@FetchRequest NSSortDescriptors - 这已经解决了它和一个谓词 - 玩得很好 10/10
    【解决方案3】:

    耶,伙计们!我解决了,我把它分成了两个这样的功能:非常感谢你的帮助!

    func loadTasks() {
            let request: NSFetchRequest<Task> = Task.fetchRequest()
            
            request.predicate = NSPredicate(format: "isDone == %@", NSNumber(value: false))
            
            request.sortDescriptors = [NSSortDescriptor(key: "isDone", ascending: false)]
            
            do{
                tasksArray = try! context.fetch(request)
            } catch {
                print("There was an error with loading items \(error)")
            }
            
            tableView.reloadData()
    
        }
        
        
        func loadDoneTasksFrom() {
            let request:NSFetchRequest<Task> = Task.fetchRequest()
    
            request.predicate = NSPredicate(format: "isDone == %@", NSNumber(value: true))
            
            request.sortDescriptors = [NSSortDescriptor(key: "isDone", ascending: false)]
            
            do{
                tasksArray = try context.fetch(request)
            } catch {
                print("Error fetching data from context\(error)")
            }
            
            tableView.reloadData()
            
        }
    

    然后在案例 0(未完成任务)的 Sege 中加载任务,在案例 1 中加载 DoneTasks。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-24
      • 2021-05-12
      • 2020-02-04
      • 2020-08-25
      • 1970-01-01
      • 2014-10-21
      • 1970-01-01
      相关资源
      最近更新 更多