在 Swift 上使用 CoreData 使用 Fetch Request 进行查询
Posted
技术标签:
【中文标题】在 Swift 上使用 CoreData 使用 Fetch Request 进行查询【英文标题】:query with Fetch Request using CoreData on Swift 【发布时间】: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()
【问题讨论】:
【参考方案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。
【讨论】:
以上是关于在 Swift 上使用 CoreData 使用 Fetch Request 进行查询的主要内容,如果未能解决你的问题,请参考以下文章
Swift 2:使用两个 CoreData 实体填充 TableView
Swift CoreData:无法在 NSManagedObject 上调用指定的初始化程序
Swift:CoreData NSManagedObject 的自定义设置器