Swift & iOS

Practice Swift syntax and compiler reasoning with choose-the-valid-line and find-the-bug exercises.

~11 min reading~3 min practice estimate
Suggest content

Swift Code Quizzes: Choose the Valid Line and Find the Bug

🟪 Syntax · 🟦 Types/APIs · 🟩 Correct pattern · 🟥 Bug · 🟨 Gotcha · 🧠 Explanation

Try each question before reading the answer key. These examples target modern Swift syntax. Some compiler diagnostics differ in wording between Xcode versions.

First: what is wrong with the Abs example?

Given:

SWIFT
protocol Abs {}
​
let value = Abs()
var value = Abs()
let: Abs = Abs()

🟥 None of these lines is a valid way to create a value. The protocol declares a contract; it is not a concrete type with a constructor. The second line also redeclares value if all lines are in the same scope, and the third line has invalid declaration syntax.

🟩 Correct version:

SWIFT
protocol Abs {}
struct ConcreteAbs: Abs {}
​
let value: any Abs = ConcreteAbs()
var replaceable: any Abs = ConcreteAbs()

The right-hand side constructs ConcreteAbs. The left-hand type any Abs says the binding may hold a value of any concrete type that conforms to Abs.

Questions

1. Which declaration creates a mutable integer binding?

SWIFT
A. let count = 0
B. var count = 0
C. Int count = 0
D. var: count Int = 0

2. Find the bug

SWIFT
let score = 10
score += 1

3. Find the bug

SWIFT
var nickname: String = nil

4. Can this let class reference still change the object's property?

SWIFT
final class Profile {
    var name = "Sam"
}
​
let profile = Profile()
profile.name = "Alex"

5. Find the conformance bug

SWIFT
protocol Drivable {
    func drive()
}
​
struct Car: Drivable {}
let car: any Drivable = Car()

6. Does this make UserID a distinct type from UUID?

SWIFT
typealias UserID = UUID
​
func openProfile(for id: UserID) {}
openProfile(for: UUID())

7. Find the concurrency bug

SWIFT
actor Counter {
    private var value = 0
    func currentValue() -> Int { value }
}
​
func printCounter(_ counter: Counter) {
    print(counter.currentValue())
}

8. Find the return-type bug

SWIFT
func greeting(_ name: String) -> String {
    print("Hello, \(name)")
}

9. Which type can go in this array?

SWIFT
import Foundation
​
protocol Identified {
    var id: UUID { get }
}
​
struct Note: Identified {
    let id: UUID
}
​
let notes: [____] = [Note(id: UUID())]

10. What happens here?

SWIFT
struct Settings {
    var theme = "light"
}
​
let settings = Settings()
settings.theme = "dark"

🟩 Answer key and explanations

🟩 1. B

var count = 0 declares a mutable binding, and Swift infers Int from 0. let creates an immutable binding. The type annotation, when needed, goes after the name: var count: Int = 0.

🟥 2. score is a let

let prevents reassignment. Use var if this value must change:

SWIFT
var score = 10
score += 1

🟥 3. String is non-optional

nil can only be assigned to an optional. If “no nickname” is a valid state, write var nickname: String? = nil. Otherwise, provide a real string value.

🟩 4. Yes

let profile prevents assigning a different Profile reference to profile. It doesn't freeze the class instance. Because name is var, profile.name can change. With a struct, a let instance and its properties are immutable.

🟥 5. Car has not implemented drive()

Car declares conformance but omits a required method. Fix the conformance:

SWIFT
struct Car: Drivable {
    func drive() {}
}

🟨 6. It is still UUID

typealias is a second name for the same type, so UUID() is accepted. For a distinct domain type, create a wrapper:

SWIFT
struct UserID: Hashable, Sendable {
    let rawValue: UUID
}

Now a function requiring UserID cannot be passed an arbitrary UUID without an explicit conversion.

🟥 7. The call needs await, and the caller must be async

Reading actor-isolated state crosses the actor boundary:

SWIFT
func printCounter(_ counter: Counter) async {
    print(await counter.currentValue())
}

An actor protects mutable state; it is not a normal synchronous object. Callers use await when accessing isolated members from outside.

🟥 8. The function promises String, but returns Void

print writes output and returns no string. Return a string instead:

SWIFT
func greeting(_ name: String) -> String {
    "Hello, \(name)"
}

Swift permits the implicit return because this function body contains one expression.

🟦 9. [any Identified]

Note is a concrete conformer, and an existential array can hold values conforming to the protocol:

SWIFT
let notes: [any Identified] = [Note(id: UUID())]

If the API needs a single concrete type relationship, use a generic function that preserves it:

SWIFT
func firstID<T: Identified>(in values: [T]) -> UUID? {
    values.first?.id
}

🟥 10. It fails because Settings is a struct held by let

Structs have value semantics. A constant struct value cannot have its var property mutated through that binding. Use var settings = Settings() if it should change, or use a class only when shared reference identity is actually needed.

More quick “spot the bug” prompts

For each one, say what the compiler rejects and how you would fix the design:

SWIFT
// A. Optional state
let selectedID: UUID = nil
​
// B. Protocol construction
protocol Parser {}
let parser = Parser()
​
// C. Immutable binding
let names = ["A", "B"]
names.append("C")
​
// D. Missing conformance requirement
protocol Resettable { func reset() }
struct Cache: Resettable {}
​
// E. Type annotation placement
let: Int total = 4

Answers: A needs UUID? if nil is valid. B needs a concrete conforming parser type. C needs var for a mutable array binding. D needs an implementation of reset() or a valid default implementation. E should be let total: Int = 4.

The declaration pattern to memorize

SWIFT
let constantName: SomeType = makeSomeType()
var variableName: SomeType = makeSomeType()

The type annotation is optional when Swift can infer it:

SWIFT
let count = 3                           // inferred as Int
var name = "Aylin"                      // inferred as String
let user: any UserLoading = LiveLoader() // existential type + concrete value

Remember: a protocol says what a conforming type can do; a struct, class, or enum gives you a concrete type to instantiate.