4

I am new to Swift & iOS dev in general.

I am building an app in SwiftUI. Assume there are 2 separate views in different files: MainView() & Results() and TabBar()(ignore the naming, this is just an example)(those 2 views are ON 2 SEPARATE TABS)

My goal is to press on that button FROM ResultsView() and change the textValue property of MainView() to something else & then display the change ON the MainView(). How can I do that? P.S Please ignore alignment & etc. I am new to StackOverflow

struct MainView: View {
    
    @State var textValue: String = "Old Text"
    
    var body: some View {
        Text(textValue)
    }
    
}

struct TabBar: View {
    var body: some View {
        TabView {
            MainView()
                .tabItem {
                    Label("Main", systemImage: "circle.dashed.inset.filled")
                }
            ResultsView()
                .tabItem {
                    Label("Results", systemImage: "person.2.crop.square.stack.fill")
                }
        }
    }
}

struct ResultsView: View {
    
    var body: some View {
        Button {
            // HOW TO UPDATE MainView.textValue?
        } label: {
            Text("Update")
        }
    }
}
  • ContentView() just has TabBar() in body

Basically, my question is how do we change UI of certain view from another view? Without NavigationLink

Might sound like a rookie question, but any reply will be so appreciated!

4
  • 1
    Look into using the @State and @Binding property wrappers for your property, there should be plenty of articles and tutorials available Commented Jan 26, 2022 at 15:26
  • Thank you! I appreciate your suggestion, but I already looked into it and I am still not able to do it. I am using tab bar navigation, so I am really lost here Commented Jan 26, 2022 at 15:44
  • Is there any way I can send you a code to look at? It is really simple, just 2 views in 2 separate tabs with 1-2 elements inside. I have been looking for solution and this would help SO MUCH Commented Jan 26, 2022 at 15:45
  • Rather than sending code to someone privately, it's probably best to update your question with a minimal reproducible example of what you've tried -- that way, anyone can answer and later, other users can try to learn from the same information. Commented Jan 26, 2022 at 16:52

1 Answer 1

3

You can achieve this by passing the textValue from MainView to DetailView through a @Binding.

struct MainView: View {
    @State private var text: String = "Original"

    var body: some View {
        NavigationView {
            VStack {
                Text(text)
                NavigationLink("Detail", destination: DetailView(text: $text))
            }
        }
    }
}

struct DetailView: View {
    @Binding var text: String
    
    var body: some View {
        Button("Change Text") {
            text = "New Text"
        }
    }
}

I recommend you read this article about bindings as it explains how to change a view from elsewhere.

Edit: Because you mentioned, that both views are in a TabBar, here should be a working example:

struct ContentView: View {
    @State private var text: String = "Original Text"
    
    var body: some View {
        TabView {
            MainView(text: $text)
                .tabItem { ... }
            DetailView(text: $text)
                .tabItem { ... }
        }
    }
}

struct MainView: View {
    @Binding var text: String

    var body: some View {
        Text(text)
    }
}

struct DetailView: View {
    @Binding var text: String

    var body: some View {
        Button("Change Text") {
            text = "New Text"
        }
    }
}
Sign up to request clarification or add additional context in comments.

10 Comments

Cameron, thank you so much! I appreciate your reply from bottom of heart. This is correct, but this is not applicable in my case, because in my case those 2 views are not connected through NavLink. Those 2 views are on separate tabs(with tab bar). I have tried creating object of MainView() and accessing the textValue property from DetailView()(let mainVC = MainView(), mainVC.username = "New Text", but it didn't work as well
Store the @State in the parent of the tab bar and pass it down to the child views via @Binding.
You can then put the @State in the View that contains the TabBar and let the MainView and DetailView have a Binding
Thank you @jnpdx! I will definitely give it a try now. This is my first month learning Swift & programming in general, so I am not really sure how to do that exactly, but I will look into it. If you share an exact code, that would be beyond amazing, but in any case I appreciate you taking the time to help out
Thank you Cameron! You guys are the best, this gives me some hope. If possible, please show me how it is done, but anyways thank you so much
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.