Thuta Learning
ProjectsProgrammingbeginner

Project: Task Manager App - Part 3 (Polish + Wrap Up)

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

What you'll walk away with

  • Apply Project: Task Manager App - Part 3 (Polish + Wrap Up) 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

Part 3 is the final stage of this project. We'll define a custom Error enum called TaskError and write throws functions to gracefully handle misuse cases like an empty title or trying to complete a non-existent id. We'll turn addTask into a throwing function with validation and use do-catch on the caller side. Finally, we'll add a printSummary() method that groups done/pending counts by priority and outputs a report format. By the end of this stage, you'll have finished a project that combines error handling, closures, structs/classes, and enums all together.

Let's build it

Define a TaskError enum with two cases, emptyTitle and taskNotFound(id: Int), conforming to the Error protocol. Turn addTask(title:priority:) into a throws function that throws TaskError.emptyTitle if title.isEmpty. Turn completeTask(id:) into throws too, throwing TaskError.taskNotFound if no matching task is found. Write a printSummary() method that prints total, done, and pending counts along with the pending count for each priority. In your main code, use a do-catch block to handle both error cases and print a user-friendly error message.

Sample Code

swift
enum TaskError: Error {
    case emptyTitle
    case taskNotFound(id: Int)
}

extension TaskManager {
    func addTask(title: String, priority: Priority) throws {
        guard !title.trimmingCharacters(in: .whitespaces).isEmpty else {
            throw TaskError.emptyTitle
        }
        let newTask = Task(id: tasks.count + 1, title: title, priority: priority)
        tasks.append(newTask)
    }

    func completeTask(id: Int) throws {
        guard let index = tasks.firstIndex(where: { $0.id == id }) else {
            throw TaskError.taskNotFound(id: id)
        }
        tasks[index].isDone = true
    }

    func printSummary() {
        print("===== Summary =====")
        print("Total: \(tasks.count), Done: \(tasks.count - pendingCount), Pending: \(pendingCount)")
        for p in [Priority.high, .medium, .low] {
            let count = tasks.filter { $0.priority == p && !$0.isDone }.count
            print("\(p.rawValue) pending: \(count)")
        }
    }
}

do {
    try manager.addTask(title: "Error handling ကျက်မယ်", priority: .high)
    try manager.completeTask(id: 99)
} catch TaskError.emptyTitle {
    print("Title လွတ်နေလို့ task ထည့်လို့ မရပါ")
} catch TaskError.taskNotFound(let id) {
    print("Task id #\(id) ကို ရှာမတွေ့ပါ")
} catch {
    print("Unknown error: \(error)")
}

manager.printSummary()
You should see
Since id #99 can't be found, the message "Task id #99 ကို ရှာမတွေ့ပါ" gets printed, and printSummary() outputs a report with pending counts broken down by priority.

Give it 5 minutes

Add a duplicateTitle case to TaskError, and write the logic yourself so addTask throws an error if a task with the same title already exists. Spend about 5 minutes on it.

One thing to watch out for

Order matters when writing catch blocks — always keep the general catch { } last, otherwise specific error cases may never be reached, and it can even cause a compile error.

Easy traps

  • Not understanding why calling a throws function without try causes a compile error
  • Putting a general catch { } at the top of your catch blocks instead of checking specific cases first, so the specific catch code never runs

Try It Yourself

Add a duplicateTitle case to TaskError, and write the logic yourself so addTask throws an error if a task with the same title already exists. Spend about 5 minutes on it.

You'll know it worked when: Since id #99 can't be found, the message "Task id #99 ကို ရှာမတွေ့ပါ" gets printed, and printSummary() outputs a report with pending counts broken down by priority.

Project: Task Manager App - Part 3 (Polish + Wrap Up) | Thuta Learning