16

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
}
J. Edgell
  • 1,555
  • 3
  • 16
  • 24

3 Answers3

32

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")
    }
stardust4891
  • 2,390
  • 1
  • 18
  • 30
8

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

Kugutsumen
  • 878
  • 8
  • 18
  • 1
    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)? – Ever Uribe Apr 22 '20 at 17:57
  • This discussion provides better context as to the mechanics of why @State variables should not be initialized as mentioned: https://forums.swift.org/t/assignment-to-state-var-in-init-doesnt-do-anything-but-the-compiler-gened-one-works/35235 – Ever Uribe Apr 23 '20 at 00:44
  • 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. – Todd Hoff Oct 21 '21 at 01:06
-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!!!!!

J. Edgell
  • 1,555
  • 3
  • 16
  • 24