20

I have a control that sets an @State variable to keep track of the selected tabs in a custom tab View. I can set the @State variable in code by setting the following:

@State var selectedTab: Int = 1

How do I set the initial value programmatically so that I can change the selected tab when the view is created?

I have tried the following:

1:

@State var selectedTab: Int = (parameter == true ? 1 : 2)

2:

init(default: Int) {
    self.$selectedTab = default
}
4
  • Have the same problem. Commented Sep 10, 2019 at 11:53
  • 2
    You are not supposed to initialize @State variables from data you pass down through the initializer; since the model is maintained outside of the view, there is no guarantee that the value will really be used. See my answer. Commented Oct 5, 2019 at 13:22
  • You should use a Binding to provide access to state that isn't local to your view. Commented Oct 5, 2019 at 13:26
  • Related answer: stackoverflow.com/a/58137096/7106170 Commented May 27, 2020 at 19:02

3 Answers 3

38

Example of how I set initial state values in one of my views:

struct TodoListEdit: View {
    var todoList: TodoList
    @State var title = ""
    @State var color = "None"

    init(todoList: TodoList) {
        self.todoList = todoList
        self._title = State(initialValue: todoList.title ?? "")
        self._color = State(initialValue: todoList.color ?? "None")
    }
Sign up to request clarification or add additional context in comments.

Comments

9

Joe Groff: "@State variables in SwiftUI should not be initialized from data you pass down through the initializer. The correct thing to do is to set your initial state values inline:"

@State var selectedTab: Int = 1

You should use a Binding to provide access to state that isn't local to your view.

@Binding var selectedTab: Int

Then you can initialise it from init and you can still pass it to child views.

Source: https://forums.swift.org/t/state-messing-with-initializer-flow/25276/3

3 Comments

But what if you have two cases, one where you want to pass data from a preceding view and another where you want to initialize with default data values (ie a creation/edit page)?
This discussion provides better context as to the mechanics of why @State variables should not be initialized as mentioned: forums.swift.org/t/…
Where do you data structure adaptation? I need to convert an array of enums to a set of strings so I can pass it to List so the user can select one or more items. The best way to do this would be to use the passed in array. So I can't really agree that this is the correct policy.
-7

This was so simple to solve once I discovered the answer!

You simply remove the initial value from the initialization by changing the declaration from:

@State var selectedTab: Int = 1

to:

@State var selectedTab: Int

and then the selectedTab variable automatically becomes a parameter in the instantiation statement. So the initialization would be:

TabBarContentView(selectedTab: 2)

Its that simple!!!!!

1 Comment

This is not working if you have to write your own init.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.