SwiftUI
custom init
@Binding
iOS development
Swift programming

SwiftUI How to implement a custom init with Binding variables

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

SwiftUI, Apple's declarative framework for building user interfaces across all Apple platforms, is a powerful tool for creating highly responsive and adaptive designs. One of the core concepts of SwiftUI is its use of @Binding variables to create reactive UIs. When developing custom SwiftUI components, it often becomes necessary to initialize these components with @Binding variables. This article will walk you through how to implement a custom initializer with @Binding variables in SwiftUI.

Understanding @Binding

Before diving into custom initialization, let's briefly revisit the concept of @Binding. In SwiftUI, @Binding is a property wrapper that provides a two-way connection to a value that is owned by a source of truth. This allows child views to read and write to a parent view's state.

Consider a simplified example of how @Binding works:

swift
1struct ContentView: View {
2    @State private var isOn: Bool = false
3
4    var body: some View {
5        ToggleView(isOn: $isOn)
6    }
7}
8
9struct ToggleView: View {
10    @Binding var isOn: Bool
11
12    var body: some View {
13        Toggle("Switch", isOn: $isOn)
14    }
15}

In this example, ToggleView has a binding to the isOn property in ContentView, allowing it to modify the state directly.

Implementing a Custom Initializer with @Binding

To initialize a component with a @Binding variable, you need to employ a custom initializer that takes the binding as a parameter. Here's a step-by-step example:

Step 1: Define the View with @Binding

Let's create a custom view CounterView that displays and modifies a count.

swift
1struct CounterView: View {
2    @Binding var count: Int
3
4    var body: some View {
5        HStack {
6            Button(action: {
7                count -= 1
8            }) {
9                Text("-")
10            }
11            Text("\(count)")
12            Button(action: {
13                count += 1
14            }) {
15                Text("+")
16            }
17        }
18    }
19}

Step 2: Custom Initializer

To initialize CounterView with a @Binding variable, define a custom initializer. Then, in the initializer, you use the underscore (_) to access the wrapped value of @Binding.

swift
1struct CounterView: View {
2    @Binding var count: Int
3
4    init(count: Binding<Int>) {
5        self._count = count // Initializing the binding
6    }
7
8    var body: some View {
9        HStack {
10            Button(action: {
11                count -= 1
12            }) {
13                Text("-")
14            }
15            Text("\(count)")
16            Button(action: {
17                count += 1
18            }) {
19                Text("+")
20            }
21        }
22    }
23}

Step 3: Use the Custom Initializer

Now, integrate CounterView into another view by passing a @State property wrapped with $, which converts it into a binding.

swift
1struct ContentView: View {
2    @State private var count: Int = 0
3
4    var body: some View {
5        CounterView(count: $count)
6    }
7}

Key Takeaways

Here's a summary of key considerations when implementing a custom initializer with @Binding variables:

Key PointSummary
Understanding @BindingUsed for two-way data binding between parent and child views in SwiftUI.
Custom InitializerRequires passing Binding<Type> and initializing with _property.
Implementation StepAccess underlying @Binding variable with self._ in initializers.
Data Flow in SwiftUISwiftUI’s state-driven UI relies on declarative data flow patterns.

Advanced Considerations

  • Preference for @Binding: Use @Binding when the child view needs to both read and modify a state. For read-only purposes, prefer @State.
  • Avoiding State Collisions: Carefully manage the source of truth to avoid unexpected state updates.
  • Localization and Accessibility: Always remember to test state changes in different localizations and ensure accessibility features adapt correctly.
  • Right Staff for the Right Task: If a view does not need to write back to a parent view's state, consider using a plain @State or computed properties to avoid unnecessary complexity.

The techniques described for custom initializers open up a new level of control and reusability in SwiftUI, allowing for more dynamic and complex interfaces, all while maintaining the OO principles that developers are familiar with. Proper management of data flow with @Binding not only makes for cleaner code but also ensures efficient and bug-free UI updates.


Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.