Consider the following Swift code snippet. What will be printed when start() is called?
class MyClass { var value = 10 func start() { DispatchQueue.global().asyncAfter(deadline: .now() + 1) { [weak self] in guard let self = self else { print("self is nil") return } print("Value is \(self.value)") } } } var obj: MyClass? = MyClass() obj?.start() obj = nil sleep(2)
Think about what happens to obj before the closure runs.
The closure captures self weakly. Since obj is set to nil before the closure executes, self inside the closure is nil. So the guard fails and prints "self is nil".
What will happen when the following Swift code runs?
class MyClass { var value = 5 func start() { DispatchQueue.global().asyncAfter(deadline: .now() + 1) { [unowned self] in print("Value is \(self.value)") } } } var obj: MyClass? = MyClass() obj?.start() obj = nil sleep(2)
Consider what happens when self is accessed after being deallocated.
Using unowned self means the closure assumes self will be alive. But obj is set to nil before the closure runs, so self is deallocated. Accessing it causes a runtime crash.
Why does the following Swift code cause a memory leak?
class ViewController { var closure: (() -> Void)? func setup() { closure = { print("Value is \(self)") } } } var vc: ViewController? = ViewController() vc?.setup() vc = nil
Think about how closures capture variables by default in Swift.
The closure captures self strongly by default. Since self holds the closure and the closure holds self, neither is released, causing a retain cycle and memory leak.
Choose the correct syntax to capture self weakly inside a closure.
class Example { func doWork() { DispatchQueue.global().async { // capture self weakly here } } }
Remember the syntax for capture lists in Swift closures.
The correct syntax uses square brackets with weak self followed by in. Option D matches this. Options A, B, and C have syntax errors.
Consider this Swift code. How many items remain in dict after the code runs?
class MyObject {} var dict = [String: MyObject]() func test() { let obj1 = MyObject() let obj2 = MyObject() dict["one"] = obj1 dict["two"] = obj2 } test() dict.removeValue(forKey: "one") print(dict.count)
Think about how dictionary keys and values behave when you remove an entry.
After adding two items, the code removes the key "one". So only the key "two" remains. The dictionary count is 1.