Sharpen your knowledge of advanced Swift programming concepts and best practices with these carefully crafted multiple-choice questions. This quiz focuses on tricky scenarios and essential Swift interview topics, making it ideal for developers preparing for technical screenings or seeking to improve their coding proficiency.
What is the most concise way to safely access a value from an optional String variable named userName for use inside a conditional block?
Explanation: Using 'if let' for optional binding lets you safely unwrap the optional, ensuring userName has a value for use inside the conditional block. Using 'if userName != nil' checks for nil but does not provide the unwrapped value. The 'guard' statement in option three should use binding for clarity and early exit, but as written, it does not bind the unwrapped value. Force unwrapping with 'userName!' is unsafe and can crash if userName is nil.
Given struct Point and var a = Point(x: 0, y: 0), what happens when you assign var b = a and then change b.x to 10?
Explanation: Structs in Swift have value semantics, which means assigning a to b creates a separate copy. Changing b.x will not affect a.x, so a.x stays 0. Option two incorrectly assumes reference semantics. There is no crash when mutating b.x, and no compilation error in this context.
If you define a protocol method in an extension and a conforming type implements its own version, which method is called when using protocol types?
Explanation: When you call a method via a variable of the protocol type and that method is only implemented in a protocol extension, the extension’s version is used, unless the method is marked as required or implemented at the protocol level. The concrete type’s own implementation isn’t used through protocol types, only direct calls on the concrete type will use its version. Only one implementation is called, and nothing fails at runtime.
Why should you use weak references for delegates, such as in delegation patterns?
Explanation: Weak references are used to avoid strong reference cycles, which can cause memory leaks, especially in delegation patterns where both objects might reference each other. Delegates are typically classes, not forbidden from being classes as option two suggests. Delegation speed is not influenced by weak vs strong references, and thread safety is unrelated to reference type in this context.
What is the highest level of access control you can give to a member so it is only accessible in the same defining file but not visible outside it?
Explanation: The 'fileprivate' access level restricts the use of a member to its own defining source file. 'Private' restricts further to the enclosing declaration only. 'Internal' allows usage anywhere in the same module, and 'public' makes it accessible outside the module, so only 'fileprivate' matches the scenario.
Suppose you have an array of type [Any] containing mixed types. Which operator should you use to safely downcast an element to a specific class type?
Explanation: Use 'as?' to safely attempt downcasting, which returns an optional that you can check for success or failure. 'as!' performs a forced cast and crashes on failure, while 'as' is for upcasting or bridging, and 'is' only checks type conformance without performing a cast.
How does using a capture list such as [weak self] in a closure prevent memory leaks?
Explanation: Capture lists like [weak self] prevent strong reference cycles by making the closure capture a weak reference to self, helping avoid memory leaks. It does not make a copy of variables, as option two says. Option three is incorrect; weak self makes self optional inside the closure. Execution timing, as in option four, is unrelated to capture lists.
What is the correct way to extract the value from an enum case with associated data when using a switch statement?
Explanation: Pattern matching in a switch enables extraction of associated values from an enum case, such as case .myCase(let value). Accessing rawValue only works with raw-value enums, not associated values. Enums can't be used like arrays or directly cast to tuples, as options three and four suggest.
Why must struct instance methods that modify self be marked with the mutating keyword?
Explanation: In Swift, methods that modify struct properties need the 'mutating' keyword to allow self or its properties to be changed, due to value semantics. Option two incorrectly suggests reference behavior. Option three is about access control, not mutability. Mutations are not strictly forbidden—using mutating enables them safely.
When should you use implicitly unwrapped optionals, like var text: String!?
Explanation: Implicitly unwrapped optionals are appropriate when a variable cannot be initialized instantly but will receive a value before it’s used, making it safe to access without explicit unwrapping later. Using them always can lead to crashes if they're nil, so option two is wrong. The compiler doesn’t check for nil at runtime (option three); instead, it crashes if nil is accessed. Option four overstates the danger; used appropriately, they are safe.