Post

iOS Developer Interview Questions

This note covers important iOS developer interview questions from beginner to advanced level.

iOS Developer Interview Questions

Topics covered:

  • Swift
  • OOP
  • Memory management
  • SwiftUI
  • UIKit
  • Lifecycle
  • Networking
  • Database
  • Concurrency
  • Architecture
  • Testing
  • Security
  • Performance
  • App Store
  • Advanced iOS topics

1. Swift Basics


Q1. What is Swift?

Swift is Apple’s modern programming language used to build apps for iOS, macOS, watchOS, tvOS, and visionOS.

Swift is:

  • Fast
  • Safe
  • Modern
  • Type-safe
  • Easy to read
  • Good for app development

Example:

1
2
let name = "Tawheed"
print("Hello, \(name)")

Q2. What is the difference between let and var?

let is used for constant values.
var is used for changeable values.

1
2
3
4
5
6
7
let appName = "My App"
var downloadCount = 10

downloadCount = 20

print(appName)
print(downloadCount)

Use let by default unless the value needs to change.


Q3. What is type inference in Swift?

Type inference means Swift can automatically understand the data type.

1
2
3
let name = "Tawheed" // Swift understands this is String
let age = 25          // Swift understands this is Int
let price = 9.99      // Swift understands this is Double

You can also define type manually:

1
2
let username: String = "Tawheed"
let count: Int = 10

Q4. What are optionals in Swift?

Optional means a value may exist or may be nil.

1
2
var username: String? = "Tawheed"
username = nil

Optional is useful when data may be missing.

Example:

1
2
3
4
5
6
7
var email: String? = nil

if let email = email {
    print(email)
} else {
    print("Email not found")
}

Q5. What is optional binding?

Optional binding safely unwraps an optional value.

1
2
3
4
5
6
7
let name: String? = "Tawheed"

if let unwrappedName = name {
    print("Name is \(unwrappedName)")
} else {
    print("Name is nil")
}

This avoids crashes.


Q6. What is guard let?

guard let safely unwraps an optional and exits early if the value is nil.

1
2
3
4
5
6
7
8
func showUserName(_ name: String?) {
    guard let name = name else {
        print("Name not found")
        return
    }

    print("Name is \(name)")
}

Use guard let when invalid data should stop the function.


Q7. What is force unwrapping?

Force unwrapping uses ! to extract an optional value.

1
2
let name: String? = "Tawheed"
print(name!)

This is risky. If value is nil, the app will crash.

Bad example:

1
2
let email: String? = nil
print(email!) // Crash

Use force unwrap only when you are 100% sure value is not nil.


Q8. What is nil coalescing operator?

Nil coalescing operator ?? provides a default value if optional is nil.

1
2
3
4
let name: String? = nil
let finalName = name ?? "Guest"

print(finalName)

Output:

1
Guest

2. Swift Data Types


Q9. What are common Swift data types?

Common data types:

1
2
3
4
5
let name: String = "Tawheed"
let age: Int = 25
let price: Double = 9.99
let isPremium: Bool = true
let rating: Float = 4.5

Q10. What is an Array?

Array stores multiple values in order.

1
2
3
let users = ["Tawheed", "John", "Sarah"]

print(users[0])

Loop example:

1
2
3
for user in users {
    print(user)
}

Q11. What is a Dictionary?

Dictionary stores key-value pairs.

1
2
3
4
5
6
let user = [
    "name": "Tawheed",
    "email": "test@example.com"
]

print(user["name"] ?? "")

Q12. What is a Set?

Set stores unique values.

1
2
3
let numbers: Set<Int> = [1, 2, 3, 3, 4]

print(numbers)

Output does not contain duplicate 3.


3. Functions and Closures


Q13. What is a function in Swift?

A function is a reusable block of code.

1
2
3
4
5
6
func greetUser(name: String) -> String {
    return "Hello, \(name)"
}

let message = greetUser(name: "Tawheed")
print(message)

Q14. What is a closure?

A closure is a block of code that can be stored or passed around.

1
2
3
4
5
let greeting: (String) -> String = { name in
    return "Hello, \(name)"
}

print(greeting("Tawheed"))

Q15. What is a trailing closure?

Trailing closure means writing the closure outside function parentheses.

1
2
3
4
5
6
7
func performTask(action: () -> Void) {
    action()
}

performTask {
    print("Task completed")
}

Q16. What is escaping closure?

An escaping closure is a closure that is executed after the function returns.

1
2
3
4
5
6
7
8
9
10
11
var savedCompletion: (() -> Void)?

func loadData(completion: @escaping () -> Void) {
    savedCompletion = completion
}

loadData {
    print("Data loaded")
}

savedCompletion?()

Use @escaping for async tasks, API callbacks, and stored closures.


4. Struct, Class, Enum, Protocol


Q17. What is a struct in Swift?

A struct is a value type.

1
2
3
4
5
6
7
struct User {
    let id: Int
    var name: String
}

let user = User(id: 1, name: "Tawheed")
print(user.name)

Structs are commonly used for models.


Q18. What is a class in Swift?

A class is a reference type.

1
2
3
4
5
6
7
8
9
10
11
12
class UserManager {
    var name = "Guest"

    func updateName(_ newName: String) {
        name = newName
    }
}

let manager = UserManager()
manager.updateName("Tawheed")

print(manager.name)

Q19. What is the difference between struct and class?

Main difference:

1
2
Struct = Value type
Class  = Reference type

Struct example:

1
2
3
4
5
6
7
8
9
10
11
struct Profile {
    var name: String
}

var profile1 = Profile(name: "A")
var profile2 = profile1

profile2.name = "B"

print(profile1.name) // A
print(profile2.name) // B

Class example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class ProfileClass {
    var name: String

    init(name: String) {
        self.name = name
    }
}

let p1 = ProfileClass(name: "A")
let p2 = p1

p2.name = "B"

print(p1.name) // B
print(p2.name) // B

Use struct for models and simple data.
Use class when shared reference or inheritance is needed.


Q20. What is an enum?

Enum represents fixed possible values.

1
2
3
4
5
6
7
enum UserType {
    case free
    case premium
    case admin
}

let type = UserType.premium

Enum with raw value:

1
2
3
4
5
6
7
enum PaymentStatus: String {
    case pending = "Pending"
    case completed = "Completed"
    case failed = "Failed"
}

print(PaymentStatus.completed.rawValue)

Q21. What is a protocol?

A protocol defines rules that a class, struct, or enum must follow.

1
2
3
4
5
6
7
8
9
protocol Downloadable {
    func download()
}

struct VideoDownloader: Downloadable {
    func download() {
        print("Download started")
    }
}

Protocols are useful for abstraction and testability.


Q22. What is protocol-oriented programming?

Protocol-oriented programming means designing code around protocols instead of inheritance.

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
protocol PaymentService {
    func pay(amount: Double)
}

class StripePaymentService: PaymentService {
    func pay(amount: Double) {
        print("Paid using Stripe")
    }
}

class CheckoutViewModel {
    private let paymentService: PaymentService

    init(paymentService: PaymentService) {
        self.paymentService = paymentService
    }

    func checkout() {
        paymentService.pay(amount: 19.99)
    }
}

This makes code flexible and testable.


Q23. What is an extension?

Extension adds new functionality to an existing type.

1
2
3
4
5
6
7
extension String {
    func addWelcomeText() -> String {
        return "Welcome, \(self)"
    }
}

print("Tawheed".addWelcomeText())

Q24. What are generics?

Generics allow writing reusable code for different data types.

1
2
3
4
5
6
7
func printValue<T>(_ value: T) {
    print(value)
}

printValue("Hello")
printValue(100)
printValue(true)

5. Error Handling


Q25. How does Swift handle errors?

Swift uses do, try, and catch.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
enum LoginError: Error {
    case invalidPassword
}

func login(password: String) throws {
    if password != "123456" {
        throw LoginError.invalidPassword
    }

    print("Login successful")
}

do {
    try login(password: "wrong")
} catch {
    print("Login failed: \(error)")
}

Q26. What is the difference between try, try?, and try!?

1
2
3
try    = normal error handling
try?   = converts result to optional
try!   = force try, crashes if error occurs

Example:

1
let result = try? login(password: "wrong")

Avoid try! unless you are 100% sure no error will happen.


6. Memory Management


Q27. What is ARC?

ARC means Automatic Reference Counting.

Swift uses ARC to manage memory automatically for class instances.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class User {
    let name: String

    init(name: String) {
        self.name = name
        print("\(name) created")
    }

    deinit {
        print("\(name) removed")
    }
}

var user: User? = User(name: "Tawheed")
user = nil

When no strong reference remains, object is removed from memory.


Q28. What is a strong reference?

A strong reference keeps an object alive.

1
2
3
4
class User {}

var user1: User? = User()
var user2 = user1

As long as user1 or user2 references the object, it stays in memory.


Q29. What is a retain cycle?

A retain cycle happens when two objects strongly hold each other, so ARC cannot remove them.

Bad example:

1
2
3
4
5
6
7
class User {
    var profile: Profile?
}

class Profile {
    var user: User?
}

If both hold each other strongly, memory leak can happen.


Q30. How to fix retain cycle?

Use weak or unowned.

1
2
3
4
5
6
7
class User {
    var profile: Profile?
}

class Profile {
    weak var user: User?
}

Use weak when the reference can become nil.


Q31. What is the difference between weak and unowned?

1
2
weak    = optional, can become nil
unowned = non-optional, should never become nil while used

Example:

1
2
3
4
5
6
7
class Parent {
    var child: Child?
}

class Child {
    weak var parent: Parent?
}

Use weak more commonly because it is safer.


Q32. How do you avoid retain cycles in closures?

Use [weak self].

1
2
3
4
5
6
7
8
9
10
11
12
13
class DownloadManager {
    var onComplete: (() -> Void)?

    func startDownload() {
        onComplete = { [weak self] in
            self?.showSuccess()
        }
    }

    func showSuccess() {
        print("Download completed")
    }
}

7. SwiftUI Basics


Q33. What is SwiftUI?

SwiftUI is Apple’s modern declarative UI framework.

Instead of describing how to change UI step by step, you describe what UI should look like based on state.

Example:

1
2
3
4
5
6
7
import SwiftUI

struct ContentView: View {
    var body: some View {
        Text("Hello SwiftUI")
    }
}

Q34. What is a View in SwiftUI?

A View is a UI component.

1
2
3
4
5
struct ProfileView: View {
    var body: some View {
        Text("Profile Screen")
    }
}

Everything in SwiftUI is a View:

  • Text
  • Button
  • Image
  • VStack
  • HStack
  • List
  • Form

Q35. What is VStack, HStack, and ZStack?

1
2
3
VStack = vertical layout
HStack = horizontal layout
ZStack = overlay layout

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct LayoutExample: View {
    var body: some View {
        VStack {
            Text("Title")

            HStack {
                Text("Left")
                Text("Right")
            }

            ZStack {
                Color.blue
                Text("Overlay Text")
                    .foregroundStyle(.white)
            }
            .frame(height: 100)
        }
    }
}

Q36. What is @State?

@State stores local view state.

1
2
3
4
5
6
7
8
9
struct CounterView: View {
    @State private var count = 0

    var body: some View {
        Button("Count: \(count)") {
            count += 1
        }
    }
}

Use @State when the view owns the data.


Q37. What is @Binding?

@Binding allows a child view to modify parent state.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct ParentView: View {
    @State private var isOn = false

    var body: some View {
        ChildView(isOn: $isOn)
    }
}

struct ChildView: View {
    @Binding var isOn: Bool

    var body: some View {
        Toggle("Enable", isOn: $isOn)
    }
}

Q38. What is @StateObject?

@StateObject creates and owns an ObservableObject.

1
2
3
4
5
6
7
8
9
10
11
class ProfileViewModel: ObservableObject {
    @Published var name = "Guest"
}

struct ProfileView: View {
    @StateObject private var viewModel = ProfileViewModel()

    var body: some View {
        Text(viewModel.name)
    }
}

Use @StateObject when the view creates the ViewModel.


Q39. What is @ObservedObject?

@ObservedObject observes an object passed from outside.

1
2
3
4
5
6
7
8
9
10
11
12
13
class CounterViewModel: ObservableObject {
    @Published var count = 0
}

struct CounterView: View {
    @ObservedObject var viewModel: CounterViewModel

    var body: some View {
        Button("Count: \(viewModel.count)") {
            viewModel.count += 1
        }
    }
}

Use @ObservedObject when parent owns the object.


Q40. What is @EnvironmentObject?

@EnvironmentObject shares an object across many views.

1
2
3
4
5
6
7
8
9
10
11
class AppSession: ObservableObject {
    @Published var isLoggedIn = false
}

struct HomeView: View {
    @EnvironmentObject var session: AppSession

    var body: some View {
        Text(session.isLoggedIn ? "Logged In" : "Guest")
    }
}

Inject:

1
2
HomeView()
    .environmentObject(AppSession())

Q41. What is @Published?

@Published notifies SwiftUI when a value changes.

1
2
3
4
5
6
7
class UserViewModel: ObservableObject {
    @Published var username = "Guest"

    func updateName() {
        username = "Tawheed"
    }
}

When username changes, UI updates automatically.


Q42. What is NavigationStack?

NavigationStack is used for navigation in SwiftUI.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct HomeView: View {
    var body: some View {
        NavigationStack {
            NavigationLink("Go to Details") {
                DetailsView()
            }
            .navigationTitle("Home")
        }
    }
}

struct DetailsView: View {
    var body: some View {
        Text("Details")
            .navigationTitle("Details")
    }
}

Q43. What is List in SwiftUI?

List shows scrollable rows.

1
2
3
4
5
6
7
8
9
struct UserListView: View {
    let users = ["Tawheed", "John", "Sarah"]

    var body: some View {
        List(users, id: \.self) { user in
            Text(user)
        }
    }
}

Q44. What is the difference between List and ScrollView?

1
2
List       = optimized list with built-in row behavior
ScrollView = flexible custom scrolling layout

Example:

1
2
3
4
5
6
7
ScrollView {
    VStack {
        ForEach(1...50, id: \.self) { item in
            Text("Item \(item)")
        }
    }
}

Use List for normal lists.
Use ScrollView for custom designs.


8. UIKit Basics


Q45. What is UIKit?

UIKit is Apple’s older UI framework for building iOS apps.

UIKit uses:

  • UIViewController
  • UIView
  • UILabel
  • UIButton
  • UITableView
  • UICollectionView
  • Auto Layout

UIKit is still important because many production apps use it.


Q46. What is UIViewController?

UIViewController manages one screen.

1
2
3
4
5
6
7
8
9
import UIKit

class HomeViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .systemBackground
    }
}

Q47. What is UIViewController lifecycle?

Important lifecycle methods:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
override func viewDidLoad() {
    super.viewDidLoad()
    print("View loaded")
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    print("View will appear")
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    print("View appeared")
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    print("View will disappear")
}

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    print("View disappeared")
}

Simple meaning:

1
2
3
4
5
viewDidLoad        Called once when view loads
viewWillAppear     Called before screen appears
viewDidAppear      Called after screen appears
viewWillDisappear  Called before screen disappears
viewDidDisappear   Called after screen disappears

Q48. What is Auto Layout?

Auto Layout is a system for creating responsive layouts.

Example:

1
2
3
4
5
6
7
8
9
10
let label = UILabel()
label.text = "Hello UIKit"
label.translatesAutoresizingMaskIntoConstraints = false

view.addSubview(label)

NSLayoutConstraint.activate([
    label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
    label.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])

Q49. What is UITableView?

UITableView displays vertical lists.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class UserTableViewController: UITableViewController {
    let users = ["Tawheed", "John", "Sarah"]

    override func tableView(
        _ tableView: UITableView,
        numberOfRowsInSection section: Int
    ) -> Int {
        return users.count
    }

    override func tableView(
        _ tableView: UITableView,
        cellForRowAt indexPath: IndexPath
    ) -> UITableViewCell {
        let cell = UITableViewCell()
        cell.textLabel?.text = users[indexPath.row]
        return cell
    }
}

Q50. What is UICollectionView?

UICollectionView displays grid or custom layouts.

Use cases:

  • Photo gallery
  • Product grid
  • Dashboard cards
  • Horizontal list
  • Custom complex lists

Simple explanation:

1
2
UITableView is mainly for vertical rows.
UICollectionView is more flexible and supports grid/custom layouts.

Q51. Can SwiftUI and UIKit work together?

Yes.

Use UIKit inside SwiftUI:

1
2
3
4
5
6
7
8
9
10
11
12
import SwiftUI
import UIKit

struct UIKitLabelView: UIViewRepresentable {
    func makeUIView(context: Context) -> UILabel {
        let label = UILabel()
        label.text = "UIKit inside SwiftUI"
        return label
    }

    func updateUIView(_ uiView: UILabel, context: Context) {}
}

Use SwiftUI inside UIKit:

1
let swiftUIView = UIHostingController(rootView: Text("SwiftUI inside UIKit"))

9. App Lifecycle


Q52. What is App lifecycle in iOS?

App lifecycle means how the app moves between states.

Common states:

1
2
3
4
5
Not Running
Inactive
Active
Background
Suspended

Q53. What is SceneDelegate?

SceneDelegate manages UI scene lifecycle in UIKit apps.

Important methods:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func sceneDidBecomeActive(_ scene: UIScene) {
    print("App active")
}

func sceneWillResignActive(_ scene: UIScene) {
    print("App inactive")
}

func sceneDidEnterBackground(_ scene: UIScene) {
    print("App background")
}

func sceneWillEnterForeground(_ scene: UIScene) {
    print("App foreground")
}

Q54. What is @main in SwiftUI app?

@main marks the app entry point.

1
2
3
4
5
6
7
8
@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

This is the starting point of a SwiftUI app.


10. Networking


Q55. How do you call an API in iOS?

Use URLSession.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct Post: Codable {
    let id: Int
    let title: String
}

func fetchPosts() async throws -> [Post] {
    let url = URL(string: "https://jsonplaceholder.typicode.com/posts")!

    let (data, response) = try await URLSession.shared.data(from: url)

    guard let httpResponse = response as? HTTPURLResponse,
          httpResponse.statusCode == 200 else {
        throw URLError(.badServerResponse)
    }

    return try JSONDecoder().decode([Post].self, from: data)
}

Q56. What is Codable?

Codable allows Swift models to convert to/from JSON.

1
2
3
4
struct User: Codable {
    let id: Int
    let name: String
}

Decode JSON:

1
let user = try JSONDecoder().decode(User.self, from: data)

Encode JSON:

1
let data = try JSONEncoder().encode(user)

Q57. How do you send a POST request?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct LoginRequest: Codable {
    let email: String
    let password: String
}

func login(email: String, password: String) async throws {
    let url = URL(string: "https://example.com/login")!

    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")

    let body = LoginRequest(email: email, password: password)
    request.httpBody = try JSONEncoder().encode(body)

    let (_, response) = try await URLSession.shared.data(for: request)

    print(response)
}

Q58. How do you add authorization token in API request?

1
2
3
4
5
6
7
8
9
10
func fetchProfile(token: String) async throws {
    let url = URL(string: "https://example.com/profile")!

    var request = URLRequest(url: url)
    request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")

    let (_, response) = try await URLSession.shared.data(for: request)

    print(response)
}

Q59. How do you handle API errors?

Create a custom error.

1
2
3
4
5
6
enum APIError: Error {
    case invalidURL
    case invalidResponse
    case decodingFailed
    case serverError(Int)
}

Use it:

1
2
3
4
5
6
7
guard let httpResponse = response as? HTTPURLResponse else {
    throw APIError.invalidResponse
}

if httpResponse.statusCode >= 500 {
    throw APIError.serverError(httpResponse.statusCode)
}

11. Local Storage


Q60. What is UserDefaults?

UserDefaults stores small key-value data.

1
2
3
UserDefaults.standard.set(true, forKey: "isPremium")

let isPremium = UserDefaults.standard.bool(forKey: "isPremium")

Use for:

  • App settings
  • Small flags
  • Simple preferences

Do not store sensitive data here.


Q61. What is AppStorage?

@AppStorage is SwiftUI wrapper for UserDefaults.

1
2
3
4
5
6
7
struct SettingsView: View {
    @AppStorage("isDarkMode") private var isDarkMode = false

    var body: some View {
        Toggle("Dark Mode", isOn: $isDarkMode)
    }
}

Q62. What is Keychain?

Keychain securely stores sensitive data.

Use Keychain for:

  • Auth token
  • Refresh token
  • Password
  • Secret keys

Simple explanation:

1
2
UserDefaults = normal small data
Keychain     = sensitive secure data

Q63. What is FileManager?

FileManager handles local files.

1
2
3
4
5
6
7
8
9
10
func saveTextFile() {
    let text = "Hello iOS"

    let url = FileManager.default.urls(
        for: .documentDirectory,
        in: .userDomainMask
    )[0].appendingPathComponent("note.txt")

    try? text.write(to: url, atomically: true, encoding: .utf8)
}

Q64. What is Core Data?

Core Data is Apple’s object graph and persistence framework.

Use Core Data for:

  • Offline database
  • Large local data
  • Complex relationships
  • Caching

Q65. What is SwiftData?

SwiftData is Apple’s modern persistence framework.

1
2
3
4
5
6
7
8
9
10
import SwiftData

@Model
class Note {
    var title: String

    init(title: String) {
        self.title = title
    }
}

SwiftData is easier and more SwiftUI-friendly than Core Data.


12. Concurrency


Q66. What is concurrency?

Concurrency means doing multiple tasks without blocking the app.

Examples:

  • API call
  • Image loading
  • File processing
  • Database query
  • Background task

Q67. What is async/await?

async/await is modern Swift concurrency.

1
2
3
4
5
6
7
8
func fetchName() async -> String {
    return "Tawheed"
}

Task {
    let name = await fetchName()
    print(name)
}

Q68. What is Task?

Task starts asynchronous work.

1
2
3
4
Task {
    let data = await loadData()
    print(data)
}

Use Task in SwiftUI for async operations.


Q69. What is MainActor?

MainActor ensures code runs on the main thread.

1
2
3
4
5
6
7
8
@MainActor
class ProfileViewModel: ObservableObject {
    @Published var username = "Guest"

    func updateName() {
        username = "Tawheed"
    }
}

UI updates should happen on main thread.


Q70. What is actor?

Actor protects shared mutable state from data races.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
actor Counter {
    private var value = 0

    func increment() {
        value += 1
    }

    func getValue() -> Int {
        return value
    }
}

let counter = Counter()

Task {
    await counter.increment()
    let value = await counter.getValue()
    print(value)
}

Q71. What is GCD?

GCD means Grand Central Dispatch.

It is an older way to handle background tasks.

1
2
3
4
5
6
7
DispatchQueue.global().async {
    print("Background work")

    DispatchQueue.main.async {
        print("Update UI")
    }
}

Modern Swift prefers async/await, but GCD is still useful to know.


13. Combine


Q72. What is Combine?

Combine is Apple’s reactive programming framework.

It handles asynchronous data streams.

Examples:

  • Search text changes
  • API responses
  • Timer events
  • Form validation
  • State updates

Q73. What is Publisher?

A Publisher emits values over time.

1
2
3
4
5
6
7
import Combine

let publisher = Just("Hello Combine")

let cancellable = publisher.sink { value in
    print(value)
}

Q74. What is AnyCancellable?

AnyCancellable stores Combine subscriptions.

1
var cancellables = Set<AnyCancellable>()

If you do not store the subscription, it may be cancelled immediately.


14. Architecture


Q75. What is MVVM?

MVVM means:

1
2
3
Model      = Data
View       = UI
ViewModel  = State and business logic

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
struct Product: Identifiable {
    let id = UUID()
    let name: String
}

class ProductViewModel: ObservableObject {
    @Published var products: [Product] = []

    func loadProducts() {
        products = [
            Product(name: "Monthly Plan"),
            Product(name: "Yearly Plan")
        ]
    }
}

struct ProductView: View {
    @StateObject private var viewModel = ProductViewModel()

    var body: some View {
        List(viewModel.products) { product in
            Text(product.name)
        }
        .onAppear {
            viewModel.loadProducts()
        }
    }
}

Q76. Why use MVVM?

MVVM helps with:

  • Cleaner code
  • Testability
  • Separation of concerns
  • Better state management
  • Easier maintenance

Q77. What is Clean Architecture?

Clean Architecture separates code into layers.

1
2
3
4
5
6
7
8
9
10
11
12
13
Presentation Layer
    View
    ViewModel

Domain Layer
    Use Cases
    Repository Protocols
    Business Models

Data Layer
    API
    Database
    Repository Implementation

Simple flow:

1
View → ViewModel → UseCase → Repository → API/Database

Q78. What is Repository Pattern?

Repository hides data source details.

1
2
3
4
5
6
7
8
9
protocol UserRepositoryProtocol {
    func getUsers() async throws -> [String]
}

class UserRepository: UserRepositoryProtocol {
    func getUsers() async throws -> [String] {
        return ["Tawheed", "John"]
    }
}

ViewModel depends on protocol:

1
2
3
4
5
6
7
8
9
10
11
12
13
class UserViewModel: ObservableObject {
    @Published var users: [String] = []

    private let repository: UserRepositoryProtocol

    init(repository: UserRepositoryProtocol) {
        self.repository = repository
    }

    func loadUsers() async {
        users = (try? await repository.getUsers()) ?? []
    }
}

Q79. What is Dependency Injection?

Dependency Injection means passing required objects from outside.

1
2
3
4
5
6
7
class AuthViewModel {
    private let repository: UserRepositoryProtocol

    init(repository: UserRepositoryProtocol) {
        self.repository = repository
    }
}

Benefits:

  • Easier testing
  • Flexible code
  • Less tight coupling

Q80. What is Coordinator Pattern?

Coordinator Pattern handles navigation outside ViewController or View.

UIKit example:

1
2
3
4
5
6
7
8
9
10
11
12
13
class AppCoordinator {
    func start() {
        print("Start app navigation")
    }

    func showLogin() {
        print("Show login screen")
    }

    func showHome() {
        print("Show home screen")
    }
}

It keeps navigation logic clean.


15. Testing


Q81. What is unit testing?

Unit testing checks small pieces of code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import XCTest

struct Calculator {
    func add(_ a: Int, _ b: Int) -> Int {
        return a + b
    }
}

final class CalculatorTests: XCTestCase {
    func testAdd() {
        let calculator = Calculator()

        let result = calculator.add(2, 3)

        XCTAssertEqual(result, 5)
    }
}

Q82. How do you test ViewModel?

1
2
3
4
5
6
7
8
9
10
11
12
13
final class LoginViewModelTests: XCTestCase {
    func testValidEmail() {
        let viewModel = LoginViewModel()

        XCTAssertTrue(viewModel.isValidEmail("test@example.com"))
    }
}

class LoginViewModel {
    func isValidEmail(_ email: String) -> Bool {
        return email.contains("@") && email.contains(".")
    }
}

Q83. What is mocking?

Mocking means creating fake dependencies for testing.

1
2
3
4
5
class MockUserRepository: UserRepositoryProtocol {
    func getUsers() async throws -> [String] {
        return ["Mock User"]
    }
}

Use mock in test:

1
let viewModel = UserViewModel(repository: MockUserRepository())

Q84. What is UI testing?

UI testing checks app screens and user interactions.

Example use cases:

  • Tap login button
  • Type email
  • Check text appears
  • Navigate screen

Simple concept:

1
2
Unit test checks logic.
UI test checks user interface behavior.

16. Security


Q85. Where should you store authentication tokens?

Use Keychain.

1
2
3
4
5
6
7
Good:
Keychain

Bad:
UserDefaults
Plain text file
Hardcoded variable

Q86. What is SSL pinning?

SSL pinning helps ensure the app talks only to the trusted server certificate/public key.

It protects against some man-in-the-middle attacks.

Simple explanation:

1
2
Normal HTTPS checks if certificate is trusted.
SSL pinning checks if certificate/public key matches your expected server.

Q87. What is App Transport Security?

App Transport Security encourages secure HTTPS connections.

Use:

1
https://api.example.com

Avoid:

1
http://api.example.com

Q88. What are common iOS security mistakes?

Common mistakes:

1
2
3
4
5
6
7
8
9
Storing token in UserDefaults
Hardcoding API keys
Logging sensitive data
Using HTTP instead of HTTPS
No certificate validation
Weak backend validation
No jailbreak/root detection for high-risk apps
Saving private files without protection
Exposing debug builds

Q89. How do you protect sensitive files?

Use file protection.

1
2
3
4
try? FileManager.default.setAttributes(
    [.protectionKey: FileProtectionType.complete],
    ofItemAtPath: fileURL.path
)

This helps protect files when device is locked.


17. Performance


Q90. How do you improve iOS app performance?

Important techniques:

1
2
3
4
5
6
7
8
9
10
11
Avoid heavy work on main thread
Use lazy loading
Optimize images
Use Instruments
Avoid memory leaks
Reduce unnecessary SwiftUI updates
Cache data properly
Optimize app launch time
Use background queues
Reuse cells in UIKit
Avoid large JSON parsing on main thread

Q91. What causes UI freezing?

UI freezes when heavy work runs on the main thread.

Bad:

1
2
3
4
func buttonTapped() {
    let result = heavyCalculation()
    print(result)
}

Better:

1
2
3
4
5
6
7
Task.detached {
    let result = heavyCalculation()

    await MainActor.run {
        print(result)
    }
}

Q92. What is Instruments?

Instruments is Apple’s performance analysis tool.

Use Instruments to find:

  • Memory leaks
  • CPU usage
  • Network usage
  • Energy usage
  • App launch time
  • Slow code
  • Retain cycles

Q93. What is a memory leak?

A memory leak happens when unused objects are not removed from memory.

Common causes:

  • Retain cycles
  • Strong closure references
  • Timers not invalidated
  • Notification observers not removed
  • Long-living references

Q94. How do you optimize images?

Best practices:

1
2
3
4
5
6
7
Use correct image size
Avoid loading huge images
Use lazy loading
Cache images
Compress images
Use async image loading
Use thumbnails where possible

SwiftUI example:

1
2
3
4
5
AsyncImage(url: URL(string: "https://example.com/image.jpg")) { image in
    image.resizable()
} placeholder: {
    ProgressView()
}

18. App Store and Release


Q95. What is TestFlight?

TestFlight is Apple’s tool for beta testing iOS apps before App Store release.

Use TestFlight for:

  • Internal testing
  • External testing
  • QA testing
  • Client review
  • Pre-release feedback

Q96. What is App Store Connect?

App Store Connect is Apple’s platform to manage apps.

You use it for:

  • Uploading builds
  • App metadata
  • Screenshots
  • Pricing
  • Subscriptions
  • TestFlight
  • App review
  • Analytics
  • Crash reports

Q97. What is provisioning profile?

A provisioning profile connects:

1
2
3
4
App ID
Certificate
Device IDs
Entitlements

It allows the app to run on devices or be distributed.


Q98. What is code signing?

Code signing proves the app was built by a trusted developer.

iOS apps must be signed before running on real devices or App Store.


Q99. What is app entitlement?

Entitlements give special capabilities to an app.

Examples:

1
2
3
4
5
6
7
Push Notifications
iCloud
App Groups
Sign in with Apple
Associated Domains
Keychain Sharing
In-App Purchase

19. Push Notifications


Q100. What is push notification?

Push notification allows server to send messages to user device.

Common use cases:

  • Chat message
  • Order update
  • Reminder
  • Marketing notification
  • Subscription alert

Q101. What is APNs?

APNs means Apple Push Notification service.

Flow:

1
2
3
4
5
Backend server
   ↓
APNs
   ↓
User device

Q102. How do you request notification permission?

1
2
3
4
5
6
7
import UserNotifications

UNUserNotificationCenter.current().requestAuthorization(
    options: [.alert, .badge, .sound]
) { granted, error in
    print("Permission granted: \(granted)")
}

20. Advanced iOS Topics


Q103. What is AVFoundation?

AVFoundation is used for audio and video.

Use cases:

  • Camera
  • Video recording
  • Audio recording
  • Video player
  • Audio processing
  • Media editing

Q104. What is Vision framework?

Vision framework is used for image analysis.

Use cases:

  • OCR
  • Face detection
  • Object detection
  • Barcode scanning
  • Image classification

Q105. What is CoreML?

CoreML allows running machine learning models on-device.

Use cases:

  • Text classification
  • Image recognition
  • Prediction
  • Audio analysis
  • AI-powered features

Q106. What is WidgetKit?

WidgetKit is used to create iOS home screen widgets.

Use cases:

  • Weather widget
  • Task widget
  • Reminder widget
  • App summary widget
  • Quick status widget

Q107. What is App Intents?

App Intents allow your app features to work with Siri, Shortcuts, Spotlight, and system actions.

Example:

1
2
3
4
5
6
7
8
9
import AppIntents

struct OpenScannerIntent: AppIntent {
    static var title: LocalizedStringResource = "Open Scanner"

    func perform() async throws -> some IntentResult {
        return .result()
    }
}

Q108. What is Background Task?

Background tasks allow limited work when app is not active.

Use cases:

  • Refresh content
  • Upload file
  • Process data
  • Sync data
  • Finish important work

iOS controls background execution strictly to save battery.


Q109. What is Deep Linking?

Deep linking opens a specific screen from a URL.

Example:

1
myapp://product/10

SwiftUI handling:

1
2
3
4
ContentView()
    .onOpenURL { url in
        print("Opened URL: \(url)")
    }

Universal Link opens your app from a normal web URL.

Example:

1
https://example.com/product/10

If app is installed, it opens the app.
If app is not installed, it opens the website.


21. Practical Scenario Questions


Q111. How would you design a login screen?

Answer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
I would use MVVM architecture.

View:
- Email field
- Password field
- Login button
- Loading state
- Error message

ViewModel:
- Validate email/password
- Call login API
- Save token securely in Keychain
- Update UI state

Repository:
- Send login request to backend

Security:
- Store token in Keychain
- Use HTTPS
- Do not log password/token

Simple UI state:

1
2
3
4
5
6
struct LoginUiState {
    var email: String = ""
    var password: String = ""
    var isLoading: Bool = false
    var errorMessage: String?
}

Q112. How would you handle API loading, success, and error state?

Use enum.

1
2
3
4
5
6
enum ViewState<T> {
    case idle
    case loading
    case success(T)
    case error(String)
}

Example:

1
@Published var state: ViewState<[User]> = .idle

This makes UI state clean.


Q113. How would you optimize a slow screen?

Steps:

1
2
3
4
5
6
7
8
9
10
Check main thread work
Use Instruments
Check network delay
Check large image loading
Check memory usage
Check unnecessary recomposition/state updates
Lazy load data
Cache API response
Move heavy work to background
Optimize database query

Q114. How would you debug a crash?

Steps:

1
2
3
4
5
6
7
8
9
10
Read crash log
Check stack trace
Reproduce issue
Use breakpoints
Check optional force unwrap
Check array index out of range
Check threading issue
Check memory issue
Fix root cause
Add test if possible

Q115. How would you secure an iOS app?

Answer:

1
2
3
4
5
6
7
8
9
10
11
Use HTTPS
Store tokens in Keychain
Avoid hardcoded secrets
Do not log sensitive data
Validate data on backend
Use certificate pinning for high-risk apps
Use file protection
Handle jailbreak risk if needed
Use proper authentication
Use token expiration
Keep dependencies updated

Q116. How would you structure a large iOS project?

Example structure:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
App/
Core/
    Network/
    Database/
    Security/
    Extensions/
    Utilities/
Features/
    Auth/
        View/
        ViewModel/
        Model/
        Repository/
    Home/
    Profile/
    Settings/
Shared/
    Components/
    Theme/
Resources/
Tests/

Clean flow:

1
View → ViewModel → UseCase → Repository → API/Database

22. Coding Interview Questions


Q117. Reverse a string in Swift

1
2
3
4
5
func reverseString(_ text: String) -> String {
    return String(text.reversed())
}

print(reverseString("Swift"))

Output:

1
tfiwS

Q118. Check palindrome

1
2
3
4
5
6
7
func isPalindrome(_ text: String) -> Bool {
    let cleaned = text.lowercased()
    return cleaned == String(cleaned.reversed())
}

print(isPalindrome("madam"))
print(isPalindrome("hello"))

Q119. Find maximum number

1
2
3
4
5
func findMax(_ numbers: [Int]) -> Int? {
    return numbers.max()
}

print(findMax([10, 5, 20, 7]) ?? 0)

Q120. Remove duplicates from array

1
2
3
4
5
func removeDuplicates(_ numbers: [Int]) -> [Int] {
    return Array(Set(numbers))
}

print(removeDuplicates([1, 2, 2, 3, 4, 4]))

If order matters:

1
2
3
4
5
6
7
8
9
10
11
12
13
func removeDuplicatesKeepingOrder(_ numbers: [Int]) -> [Int] {
    var seen = Set<Int>()
    var result: [Int] = []

    for number in numbers {
        if !seen.contains(number) {
            seen.insert(number)
            result.append(number)
        }
    }

    return result
}

Q121. Count character frequency

1
2
3
4
5
6
7
8
9
10
11
func characterCount(_ text: String) -> [Character: Int] {
    var result: [Character: Int] = [:]

    for char in text {
        result[char, default: 0] += 1
    }

    return result
}

print(characterCount("hello"))

Q122. FizzBuzz

1
2
3
4
5
6
7
8
9
10
11
12
13
func fizzBuzz() {
    for number in 1...100 {
        if number % 3 == 0 && number % 5 == 0 {
            print("FizzBuzz")
        } else if number % 3 == 0 {
            print("Fizz")
        } else if number % 5 == 0 {
            print("Buzz")
        } else {
            print(number)
        }
    }
}

23. Senior-Level Questions


Q123. How do you decide between SwiftUI and UIKit?

Answer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Use SwiftUI:
- New apps
- Faster UI development
- Declarative UI
- Modern Apple ecosystem
- Simple to medium complex UI

Use UIKit:
- Existing legacy apps
- Complex custom controls
- Advanced collection layouts
- Better mature control over UI
- When team already uses UIKit

Best senior answer:
I can work with both and also integrate SwiftUI inside UIKit or UIKit inside SwiftUI when needed.

Q124. How do you prevent massive ViewModels?

Answer:

1
2
3
4
5
6
Move business logic into UseCases
Move API/database logic into Repository
Use smaller feature-specific ViewModels
Keep ViewModel focused on UI state
Use services for reusable logic
Use dependency injection

Bad:

1
ViewModel does API + validation + database + navigation + formatting

Good:

1
ViewModel handles UI state and calls UseCases

Q125. How do you handle offline-first apps?

Answer:

1
2
3
4
5
6
7
Store data locally
Show cached data first
Sync with server when internet is available
Handle conflict resolution
Queue pending operations
Use background sync
Show sync status to user

Flow:

1
UI → Local Database → Repository → API Sync

Q126. How do you handle token refresh?

Answer:

1
2
3
4
5
6
Access token expires quickly
Refresh token lives longer
When API returns 401, call refresh token API
Save new access token securely
Retry original request
If refresh fails, logout user

Important:

1
2
Store tokens in Keychain.
Never store tokens in plain UserDefaults.

Q127. How do you handle large file upload?

Answer:

1
2
3
4
5
6
7
8
Use background URLSession
Show upload progress
Support retry
Validate file size
Compress file if needed
Handle network failure
Do not block main thread
Secure upload API

Q128. How do you improve app launch time?

Answer:

1
2
3
4
5
6
7
Avoid heavy work in app startup
Delay non-critical SDK initialization
Optimize dependency loading
Reduce initial API calls
Use lazy loading
Avoid large database work on main thread
Profile with Instruments

Q129. How do you make iOS app scalable?

Answer:

1
2
3
4
5
6
7
8
9
10
Use clean architecture
Feature-based modules
Dependency injection
Reusable components
Clear state management
Good error handling
Testing
Logging
Documentation
CI/CD

Q130. What makes you a strong iOS developer?

A strong answer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
A strong iOS developer does not only write UI.
They build stable, secure, fast, maintainable, and user-friendly apps.

They understand:
- Swift deeply
- SwiftUI and UIKit
- Architecture
- API integration
- Local storage
- Memory management
- Performance
- Security
- Testing
- App Store release
- Product experience

Final Interview Preparation Checklist

Before an iOS interview, revise these topics:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Swift basics
Optionals
Struct vs Class
Protocol
Extension
Generics
Closure
ARC
Weak and unowned
Retain cycle
SwiftUI state management
UIKit lifecycle
Navigation
URLSession
Codable
Async/await
MainActor
Actor
UserDefaults
Keychain
Core Data / SwiftData
MVVM
Clean Architecture
Repository Pattern
Dependency Injection
Testing
Debugging
Performance
Security
Push Notification
App Store release
Advanced frameworks

Final Advice

For interviews, do not memorize only definitions.

For every question, answer in this format:

1
2
3
4
1. Simple definition
2. Why it is used
3. Small example
4. Real app use case

Example:

1
2
3
4
5
6
7
Question: What is Keychain?

Answer:
Keychain is secure storage provided by Apple.
It is used to store sensitive data like auth tokens and passwords.
Unlike UserDefaults, Keychain is encrypted and more secure.
In real apps, I would store access tokens and refresh tokens in Keychain, not in UserDefaults.

This style sounds professional, practical, and interview-ready.

This post is licensed under CC BY 4.0 by the author.