iOS Interview Questions: SwiftUI

Updated Nov 08, 2022#ios#swift#swiftui

The existence of SwiftUI has somehow rendered UIKit obsolete, you should get busy learning SwiftUI because it is the future of app development on Apple platforms.

Will SwiftUI replace UIKit?

SwiftUI was announced at WWDC 19 as a declarative framework to declare user interface for any Apple platform. You can integrate SwiftUI views with objects from the UIKit, AppKit, and WatchKit frameworks to take further advantage of platform-specific functionality.

@available(iOS 13, macOS 10.15, *)
struct MyView: View {
  var body: some View {
    Text("Hello, World!")
  }
}

SwiftUI is absolutely going to be the future of development for Apple’s platforms, but it will take a long time to gain adoption at the level of UIKit. As each year goes by, SwiftUI grows in strength, adoption, and support, and as SwiftUI grows UIKit will start to shrink.

What is declarative UI programming?

Declarative UI programming patterns have become incredibly popular over the last few years. On the web with frameworks like React and Vue.js, in cross-platform development environments like React Native and Flutter, and through native tools like RxSwift and RxCocoa.

One key aspect of most declarative UI frameworks is that they aim to boil any kind of UI down into a series of components — which can then be combined and composed in order to form different sets of views, animations, and interactions.

Difference between @StateObject and @ObservedObject?

class DataModel: ObservableObject {
  /* ... */
}

struct FooView: View {
  @StateObject private var model = DataModel()
  var body: some View {
    VStack {
      BarView(model: model)
    }
  }
}

struct BarView: View {
  @ObservedObject var model: DataModel
  var body: some View {
    Text("Hello")
  }
}

A property marked as @StateObject will keep its initially assigned ObservableObject instance as long as the view is needed, even when the struct gets recreated by SwiftUI.

An @ObservedObject is used to wrap ObservableObject instances that are not created or owned by the view that’s used in. Internally, SwiftUI will not keep an @ObservedObject around when it discards and recreates a view if this is needed for a fresh render.

What are the benefits of using SwiftUI?

  • SwiftUI offers a unified UI framework for building user interfaces on all types of Apple devices.
  • SwiftUI has a declarative syntax which easy to use and learn.
  • SwiftUI has very simple, modern and clean syntax.
  • SwiftUI promotes reactive programming through Binding, State and the Combine.
  • SwiftUI provides a live preview using the canvas, an interactive interface editor.
  • SwiftUI integrates well with both UIKit and AppKit, it enables us to incrementally migrate existing projects.

Why does SwiftUI use structs for views?

Swift provides a number of features that make structs better than classes in performance and thread-safety.

Structs are preferable if they are relatively small and copiable because copying is way safer than having multiple references to the same instance as happens with classes.

With Structs, there is much less need to worry about memory leaks or multiple threads racing to access/modify a single instance of a variable. This is especially important when passing around a variable to many classes and/or in a multithreaded environment. If you can always send a copy of your variable to other places, you never have to worry about that other place changing the value of your variable underneath you.

How does an observable object announce changes?

ObservableObject is a type of object with a publisher that emits before the object has changed. By default an ObservableObject synthesizes an objectWillChange publisher that emits the changed value before any of its @Published properties changes.

Using @Published is the easiest way to control state updates, you can also call objectWillChange.send() manually to put out the news that our data has changed so that any subscribed views can refresh.

class Model: ObservableObject {
  @Published var name: String

  var age: Int {
    willSet {
      objectWillChange.send()
    }
  }

  init(name: String, age: Int) {
      self.name = name
      self.age = age
  }
}

Why always declare state as private?

SwiftUI manages the storage of a property that you declare as state. When the value changes, SwiftUI updates the parts of the view hierarchy that depend on the value. Use state as the single source of truth for a given value stored in a view hierarchy.

struct PlayButton: View {
  @State private var isPlaying: Bool = false

  var body: some View {
    Button(isPlaying ? "Pause" : "Play") {
      isPlaying.toggle()
    }
  }
}

Don’t initialize a state property of a view at the point in the view hierarchy where you instantiate the view, because this can conflict with the storage management that SwiftUI provides.

To avoid this, always declare state as private, and place it in the highest view in the view hierarchy that needs access to the value. Then share the state with any child views that also need access, either directly for read-only access, or as a binding for read-write access.

Does the order of SwiftUI modifiers matter?

When a modifier just changes the environment that its target view will be rendered in, then the order often doesn’t matter.

However, if that modifier can only be applied to a specific type of view, then we can only apply it as long as we’re dealing with that kind of view directly.

The order of modifiers that wrap their target view, on the other hand, often matters quite a lot, and a different modifier order can end up yielding a very different result.