Do-try-catch execution flow in Swift - Time & Space Complexity
When using do-try-catch in Swift, it's important to see how the program runs depending on success or failure.
We want to know how the number of steps changes as the code tries to run and handle errors.
Analyze the time complexity of the following code snippet.
func readFile(name: String) throws -> String {
// Imagine this reads a file and may throw an error
return "File content"
}
func processFile(name: String) {
do {
let content = try readFile(name: name)
print(content)
} catch {
print("Error reading file")
}
}
This code tries to read a file and prints its content if successful, or prints an error message if it fails.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Calling
readFileonce inside thedoblock. - How many times: Exactly one time per
processFilecall.
Explain the growth pattern intuitively.
| Input Size (n) | Approx. Operations |
|---|---|
| 1 | 1 try + 1 print |
| 10 | 10 tries + 10 prints (if called 10 times) |
| 100 | 100 tries + 100 prints (if called 100 times) |
Pattern observation: Each call to processFile performs exactly one try and one print (either content or error). Thus, the number of operations grows linearly with the number of calls.
Time Complexity: O(1) per call to processFile
This means the time is constant and does not grow with input size within a single call.
[X] Wrong: "The catch block runs multiple times inside one call if an error happens."
[OK] Correct: The catch block runs only once per try. It does not loop or repeat inside the same call.
Understanding how do-try-catch flows helps you explain error handling clearly and shows you know how code runs step-by-step.
"What if the readFile function called itself recursively? How would the time complexity change?"
Practice
do-try-catch in Swift?Solution
Step 1: Understand the role of
This structure is used to run code that might throw errors and handle those errors gracefully.do-try-catchStep 2: Identify the purpose
It prevents the program from crashing by catching errors and allowing alternative actions.Final Answer:
To handle errors safely without crashing the program -> Option AQuick Check:
Error handling = A [OK]
- Confusing error handling with loops
- Thinking try-catch defines functions
- Assuming it declares variables
do-try-catch block in Swift?Solution
Step 1: Recall correct
The correct syntax starts withdo-try-catchsyntaxdo {}, inside whichtryis used before the function that might throw.Step 2: Match syntax with options
do { try someFunction() } catch { handleError() } correctly placesdoblock, usestryinside, and follows withcatchblock.Final Answer:
do { try someFunction() } catch { handleError() } -> Option DQuick Check:
Correct syntax = D [OK]
- Placing try outside do block
- Swapping catch and do blocks
- Missing curly braces
enum MyError: Error { case fail }
func risky() throws {
throw MyError.fail
}
do {
try risky()
print("Success")
} catch {
print("Caught an error")
}Solution
Step 1: Analyze the function
This function always throws an error of typerisky()MyError.fail.Step 2: Trace the
Whendo-try-catchblocktry risky()runs, it throws an error, so the code jumps to thecatchblock and prints "Caught an error".Final Answer:
Caught an error -> Option BQuick Check:
Error thrown = catch block runs = B [OK]
- Assuming code after try runs despite error
- Thinking no output occurs
- Confusing compile error with runtime error
do {
try someFunction()
} catch error {
print("Error: \(error)")
}
func someFunction() {
print("Running")
}Solution
Step 1: Check function declaration
The functionsomeFunction()is called withtry, so it must be declared withthrowsto indicate it can throw errors.Step 2: Identify mismatch causing error
SincesomeFunction()is not markedthrows, the compiler will raise an error.Final Answer:
Function someFunction() must be marked with throws -> Option AQuick Check:
try requires throws function = C [OK]
- Ignoring throws keyword on function
- Thinking catch syntax is wrong
- Assuming print inside catch is invalid
enum FileError: Error { case notFound, unreadable }
func readFile(_ name: String) throws -> String {
if name == "missing.txt" { throw FileError.notFound }
if name == "bad.txt" { throw FileError.unreadable }
return "File content"
}
do {
let content = try readFile("bad.txt")
print(content)
} catch FileError.notFound {
print("File not found")
} catch {
print("Other error")
}Solution
Step 1: Analyze the function call
CallingreadFile("bad.txt")throwsFileError.unreadable.Step 2: Check catch blocks for matching error
The first catch handlesFileError.notFound, which does not match. The second catch is a general catch that handles all other errors, so it runs and prints "Other error".Final Answer:
Other error -> Option CQuick Check:
Specific catch misses, general catch runs = A [OK]
- Assuming first catch runs for all errors
- Thinking no output occurs
- Confusing error types
Ready to prove it?
Pass the test and this pattern moves unknown
