@State variable initialization in SwiftUI
source link: https://sarunw.com/posts/state-variable-initialization/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
@State variable initialization in SwiftUI
Table of Contents
There might be a time when you want to initialize the value of a @State
variable in an initializer.
struct CounterView: View {
@State private var count: Int
init(count: Int) {
self.count = count
}
...
}
Since Xcode 14, you can easily do this.
The bigger question is not how we can do it. But should we do it?
Let's learn how to do it and then judge for yourselves whether you want to do it or not.
You can easily support sarunw.com by checking out this sponsor.
Sponsor sarunw.com and reach thousands of iOS developers.
How to initialize @State variable in an initializer
Here is an example of CounterView
, which has its own count
state property.
struct CounterView: View {
@State private var count = 0
var body: some View {
VStack {
Text("Counter: \(count)")
Button("+1") {
count += 1
}
}
}
}
We can use it like this.
struct ContentView: View {
var body: some View {
CounterView()
.font(.title)
}
}
A view with a state variable.
If we want other views to set the initial count value of the CounterView
, we need to create an initializer that sets the count
property.
Since Xcode 14, we can do it just like a normal variable.
struct CounterView: View {
@State private var count: Int
init(count: Int) {
self.count = count
}
var body: some View {
VStack {
Text("Counter: \(count)")
Button("+1") {
count += 1
}
}
}
}
In the past, initializing a @State
variable like this wasn't possible. You have to initialize it in the property wrapper way like this _count = State(initialValue: count)
.
You might encounter a solution like this on the internet, but we no longer need this since the compiler is smarter now (Xcode 14).
struct CounterView: View {
@State private var count: Int
init(count: Int) {
_count = State(initialValue: count)
}
var body: some View {
VStack {
Text("Counter: \(count)")
Button("+1") {
count += 1
}
}
}
}
Then we can use it like this.
struct ContentView: View {
var body: some View {
CounterView(count: 5)
.font(.title)
}
}
We initialize CounterView(count: 5)
with count
variable set to five. When we run the app, this is what we got.
A CounterView initial count is five.
Should we initialize @State variable in an initializer
As you can see, our previous example works very well. We can control the @State
variable from the call site.
But there is a behavior that you should be aware of.
Setting a @State
variable like this will only work for the very First time. After the @State
variable is create and initialize, SwiftUI will make sure it persisted through the lifetime of the view.
That means the subsequence change of count
value from the initializer won't take any effect.
It might be easier to understand this with an example.
In this example, instead of hard-coded count
value to five, CounterView(count: 5)
, we make it changeable using @State private var externalCount = 2
.
struct ContentView: View {
// 1
@State private var externalCount = 2
var body: some View {
VStack {
// 2
CounterView(count: externalCount)
Text("External Count: \(externalCount)")
Button("External +1") {
// 3
externalCount += 1
}
}
.font(.title)
}
}
1 We create @State
variable to represent an initial value for our CounterView
.
2 We use the @State
variable, externalCount
, to initalize CounterView
.
3 We create a button to increase value of externalCount
.
On the first launch, CounterView
was initialized with externalCount
, which had an initial value of two.
And that's it, CounterView.count
is created and persisted.
Even if we change the value of externalCount
later, it no longer affects the value of the CounterView
.
The change in the externalCount value has no affects on the CounterView.
You can easily support sarunw.com by checking out this sponsor.
Sponsor sarunw.com and reach thousands of iOS developers.
Conclusion
A @State
variable means to use internally within a view. Apple suggested we always declare state variables as private
.
As you can see, Apple suggested that with a good reason. Exposing a state variable as we did might cause confusing to a newcomer or even your future self since the state variable can only initialize once.
If you need to initialize a state property like this, it might be a good time to reorganize your view. Maybe some data is sitting in the wrong places.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK