Curated iOS Interview Questions Series — Part 4

Rahul Goel
4 min readApr 16, 2024

--

Series aiming to cover as many Q&A’s as possible from iOS interview perspective.

Do check out Part-1, Part-2, Part-3 before proceeding further.

43. retain vs strong difference?

In summary, retain and strong are similar in their effect on memory management, but retain is used in the context of manual reference counting, while strong is used in the context of automatic reference counting.

44. Difference between autorelease and release in MRC?

When you call the release method on an object, its reference count is immediately decremented by one. In contrast, when you call the autorelease method on an object, its reference count is not decremented immediately, but instead added to the autorelease pool. The autorelease pool is a collection of objects that are released at a later time, typically at the end of the current run loop iteration.

45. Struct vs classes which is thread safe and why?

struct are thread-safe. as memory allocation happens in stack for structs and there is separate stack for every thread. where you pass around value types it is copied into the stack thread.

Whereas classes or ref types uses heap for memory allocation.

46. Implement Multi -Set in Swift.

It’s a collection that can store elements with their multiplicity, meaning how many times each element appears or its a set with frequency of each unique element.

struct MultiSet<Element: Hashable> {
private var storage: [Element: Int] = [:]

mutating func insert(_ element: Element) {
storage[element, default: 0] += 1
}

mutating func remove(_ element: Element) {
if let count = storage[element] {
if count > 1 {
storage[element] = count - 1
} else {
storage.removeValue(forKey: element)
}
}
}

func count(of element: Element) -> Int {
return storage[element, default: 0]
}
}

//Usage:

var multiSet = MultiSet<String>()

multiSet.insert("apple")
multiSet.insert("banana")
multiSet.insert("apple")

print("Count of apple:", multiSet.count(of: "apple")) // Output: Count of apple: 2

multiSet.remove("apple")

print("Count of apple after removal:", multiSet.count(of: "apple")) // Output: Count of apple after removal: 1

47. Find closest parent view of two UIViews.

func findClosestCommonParentFor(view1: UIView, view2: UIView) -> UIView? {
var path1 = [UIView]()
var path2 = [UIView]()

// Trace path for view1
var currentView: UIView? = view1
while let view = currentView {
//Store view Info
path1.append(view)
//Get SuperView and make it cur
currentView = view.superview
}

// Trace path for view2
currentView = view2
while let view = currentView {
//Store view Info
path2.append(view)
//Get SuperView and make it current
currentView = view.superview
}

// Convert path2 into a Set
let setT = Set(path2)

// Find the closest common ancestor
for ancestor in path1 {
if setT.contains(ancestor) {
return ancestor
}
}

return nil // No common ancestor found
}

48. How to make swift arrays thread safe.

var threadSafeArray: [Element] = []
let queue = DispatchQueue(label: "com.example.arrayAccess", attributes: .concurrent)

// Writing to the array in a thread-safe manner
queue.async(flags: .barrier) {
threadSafeArray.append(newElement)
}

// Reading from the array in a thread-safe manner
queue.sync {
let element = threadSafeArray[index]
}

49. Add Debouncing in search bar when user type characters.

Debouncing is a technique used to delay the execution of a function until after a certain amount of time has passed since the last invocation of that function. In the context of a search bar, debouncing can be used to delay the search operation until the user has stopped typing for a short period. This prevents the search operation from being triggered too frequently while the user is still typing.

import UIKit

class ViewController: UIViewController, UISearchBarDelegate {
@IBOutlet weak var searchBar: UISearchBar!

// Define a timer to handle debouncing
private var debounceTimer: Timer?

override func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
// Cancel the previous debounce timer
debounceTimer?.invalidate()

// Start a new debounce timer
debounceTimer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { [weak self] _ in
// Perform search operation here
self?.performSearch(with: searchText)
}
}

func performSearch(with searchText: String) {
// Perform your search operation here
print("Searching for: \(searchText)")
}
}

50. How to unwrap optional type with default value.

extension Optional where Wrapped: ExpressibleByIntegerLiteral {
func customUnwrap() -> Wrapped {
switch self {
case .none:
return 0
case .some(let value):
return value
}
}
}

extension Optional where Wrapped == String {
func customUnwrap() -> String {
switch self {
case .none:
return ""
case .some(let value):
return value
}
}
}

//Usage

var optionalInt: Int?
let unwrappedInt = optionalInt.customUnwrap()
print("Unwrapped Int: \(unwrappedInt)")

let optionalString: String? = "Hello, World!"
let unwrappedString = optionalString.customUnwrap()
print("Unwrapped String: \(unwrappedString)")

Follow me Rahul Goel for further updates.

--

--

Rahul Goel
Rahul Goel

Written by Rahul Goel

Computer Science Enthusiast | 11+ Year of Software Evolution | @Sharechat, Groupon, Paytm, Myntra https://www.linkedin.com/in/therahulgoel/