Reputation: 61
Sorry guys if there's already a thread about it but been stuck with it for a while.
I'm kinda new to CoreData(knows only how to persist and fetch items only) and I'm trying to do a little query in my app which will load only the ones with the isDone attribute = to "True".
the thing is I don't know how to use NSFetchRequest & NSPredicate so im kinda stuck, hope you guys can help me out with some tips <3, Here's my code:
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()
}
}
Upvotes: 0
Views: 2019
Reputation: 61
Yay fellas! I solved it, I splited it to two functions like this: thank you very much for your help ! <3 I've learned how to use CoreData :) much love!.
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()
}
and then in the Sege for case 0(not done task) I loadTasks, and in case1 I load DoneTasks.
Upvotes: 0
Reputation: 1443
You can write queries like this
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
}
And then you just fetch them with:
@FetchRequest(fetchRequest: Task.getDoneTasks()) var doneTasks: FetchedResults<Task>
You also can add arguments etc. to your function and pass them in the FetchRequest
I can recommend this tutorial to understand the core concepts of coredata
Upvotes: 1
Reputation: 1778
You can use one of these
NSPredicate(format: "isDone == %@", NSNumber(value: true))
NSPredicate(format: "isDone = %d", true)
Upvotes: 1