Thuta Learning
ProjectsProgrammingbeginner

Project: Task Manager App - Part 2 (Adding the Main Feature)

Relax. We'll talk through this in plain words — no textbook voice.

What you'll walk away with

  • Apply Project: Task Manager App - Part 2 (Adding the Main Feature) in a hands-on project
  • Write and run the code yourself
  • Build out an entire project step by step

Let's think about this for a second

In this part, we'll add the core features — task completion, filtering, sorting — to the TaskManager we built in Part 1. We'll write a method that accepts a closure as a parameter and filters the task list by a custom condition, which is practice for the higher-order function pattern. We'll use sorted(by:) with a custom comparator closure to sort by priority. We'll write the pending task count as a computed property so it needs no get/set logic, reinforcing the properties topic. By the end of this stage, the app becomes a tool that does practical operations, not just holds data.

Let's build it

Write a completeTask(id: Int) method that sets isDone to true on the task with the matching id (find the array index with firstIndex(where:)). Write a filter(by condition: (Task) -> Bool) -> [Task] method that filters the task array using a closure condition. Write a tasks(sortedBy:) method that returns the array sorted from high to low priority. Add a var pendingCount: Int computed property that returns the count of tasks where isDone == false. Update printAllTasks() to print in sortedBy priority order.

Sample Code

swift
extension TaskManager {
    func completeTask(id: Int) {
        if let index = tasks.firstIndex(where: { $0.id == id }) {
            tasks[index].isDone = true
        }
    }

    func filter(by condition: (Task) -> Bool) -> [Task] {
        return tasks.filter(condition)
    }

    func tasksSortedByPriority() -> [Task] {
        let order: [Priority] = [.high, .medium, .low]
        return tasks.sorted {
            order.firstIndex(of: $0.priority)! < order.firstIndex(of: $1.priority)!
        }
    }

    var pendingCount: Int {
        return tasks.filter { !$0.isDone }.count
    }
}

manager.completeTask(id: 1)
let highPriorityTasks = manager.filter { $0.priority == .high }
print("High priority pending: \(highPriorityTasks.count)")
print("Total pending: \(manager.pendingCount)")
You should see
After calling completeTask, pendingCount drops by one, and the high-priority filter result also prints the correct array.

Give it 5 minutes

Write a line yourself that filters out only the tasks where isDone == true, and add a computed property called completedCount. Spend about 5 minutes on it.

One thing to watch out for

Since array elements are the Task value type, you need to mutate them directly by index, like tasks[index].isDone = true — changing the local copy inside a for task in tasks loop won't change the original array.

Easy traps

  • Writing long manual filter loops with for instead of using closure-based filter/sorted on the tasks array
  • In completeTask(id:), force-unwrapping the result of firstIndex(where:) instead of optional binding, causing crashes

Try It Yourself

Write a line yourself that filters out only the tasks where isDone == true, and add a computed property called completedCount. Spend about 5 minutes on it.

You'll know it worked when: After calling completeTask, pendingCount drops by one, and the high-priority filter result also prints the correct array.

Project: Task Manager App - Part 2 (Adding the Main Feature) | Thuta Learning