I have got two tabItems in TabView with FirstScreen and PlacesScreen. FirstScreen contains picker with items located in array in the model PlacesViewModel. The same model is used for the list from the second tabItem on PlacesScreen. By choosing a particular item in picker and pressing button, I have to open the second tabItem and open a particular row in the list on PlacesScreen. I have figured out how to open the second tabItem but stuck with opening a particular row.
The first screen code with picker and button:
struct FirstScreen: View {
@EnvironmentObject var placesViewModel: PlacesViewModel
@State var placeChoice = 0
@Binding var tabSelection: Int
var body: some View {
NavigationView {
Form {
VStack {
Picker("Places", selection: $placeChoice) {
ForEach(0 ..< placesViewModel.places.count) { index in
Text(placesViewModel.places[index].name)
.tag(index)
}
}.pickerStyle(WheelPickerStyle())
Button {
tabSelection = 1
} label: {
Text("Show place")
.font(.system(size: 20))
.padding()
.foregroundColor(.white)
.background(Color.blue)
.cornerRadius(8)
}
}
}
.navigationTitle("First Screen")
}
}
}
struct FirstScreen_Previews: PreviewProvider {
static var previews: some View {
FirstScreen(tabSelection: .constant(0))
}
}
The second screen with a List:
struct PlacesScreen: View {
var body: some View {
PlacesList()
}
}
struct PlacesScreen_Previews: PreviewProvider {
static var previews: some View {
PlacesScreen()
}
}
struct PlacesList: View {
@EnvironmentObject var placesViewModel: PlacesViewModel
var body: some View {
NavigationView {
List(placesViewModel.places) { place in
NavigationLink {
PlaceScreen(place: place)
} label: {
HStack {
place.image
.resizable()
.frame(width: 50, height: 50)
Text(place.name)
Spacer()
}
}
}
.navigationTitle(placesViewModel.title)
}
}
}
struct PlacesList_Previews: PreviewProvider {
static var previews: some View {
PlacesList()
}
}
Here is the TabView code:
struct ContentView: View {
@State var tabSelection: Int = 0
var body: some View {
TabView(selection: $tabSelection) {
FirstScreen(tabSelection: tabSelection)
.tag(0)
.tabItem {
Label("First Screen", systemImage: "list.bullet.rectangle")
}
PlacesScreen()
.tag(1)
.tabItem {
Label("Places", systemImage: "tray.2.fill")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Thank you in advance for your help!
You can use NavigationLink(tag: selection:). Here is a fully functional demo based on your code.
struct ContentView: View {
@State var placeChoice: String?
@State private var tabSelection: Int = 0
var body: some View {
TabView(selection: $tabSelection) {
FirstScreen(placeChoice: $placeChoice, tabSelection: $tabSelection)
.tabItem {
Label("One", systemImage: "mappin.circle.fill")
}
.tag(0)
PlacesList(placeChoice: $placeChoice)
.tabItem {
Label("Two", systemImage: "mappin.circle.fill")
}
.tag(1)
}
}
}
let places = ["Paris", "Rome", "Berlin", "London", "Madrid", "Oslo"]
struct FirstScreen: View {
@Binding var placeChoice: String?
@Binding var tabSelection: Int
@State private var pickerChoice: String = "Rome"
var body: some View {
NavigationView {
Form {
VStack {
Picker("Places", selection: $pickerChoice) {
ForEach(places, id: \.self) { place in
Text(place)
.tag(place)
}
}
// .pickerStyle(.segmented)
.pickerStyle(WheelPickerStyle())
Button {
placeChoice = pickerChoice
tabSelection = 1
print("*******", placeChoice)
} label: {
Text("Show place")
.font(.system(size: 20))
.padding()
.foregroundColor(.white)
.background(Color.blue)
.cornerRadius(8)
}
}
}
.navigationTitle("First Screen")
}
}
}
struct PlacesList: View {
@Binding var placeChoice: String?
var body: some View {
NavigationView {
List {
ForEach(places, id: \.self) { place in
NavigationLink(tag: place, selection: $placeChoice) {
//PlaceScreen(place: place)
Text("Detail screen \(place)")
} label: {
HStack {
//place.image
Image("image")
.resizable()
.frame(width: 50, height: 50)
Text(place)
Spacer()
}
}
}
}
.navigationTitle("Places")
}
}
}
And this is the version using the new iOS16 NavigationStack
:
struct ContentView: View {
// iOS16 Navigation Path
@State private var navPath: [String] = []
@State private var tabSelection: Int = 0
var body: some View {
TabView(selection: $tabSelection) {
FirstScreen(navPath: $navPath, tabSelection: $tabSelection)
.tabItem {
Label("One", systemImage: "mappin.circle.fill")
}
.tag(0)
PlacesList(navPath: $navPath)
.tabItem {
Label("Two", systemImage: "mappin.circle.fill")
}
.tag(1)
}
}
}
let places = ["Paris", "Rome", "Berlin", "London", "Madrid", "Oslo"]
struct FirstScreen: View {
@Binding var navPath: [String]
@Binding var tabSelection: Int
@State private var pickerChoice: String = "Rome"
var body: some View {
NavigationStack {
Form {
VStack {
Picker("Places", selection: $pickerChoice) {
ForEach(places, id: \.self) { place in
Text(place)
.tag(place)
}
}
.pickerStyle(WheelPickerStyle())
Button {
navPath = [pickerChoice]
tabSelection = 1
print("*******", navPath)
} label: {
Text("Show place")
.font(.system(size: 20))
.padding()
.foregroundColor(.white)
.background(Color.blue)
.cornerRadius(8)
}
}
}
.navigationTitle("First Screen")
}
}
}
struct PlacesList: View {
@Binding var navPath: [String]
var body: some View {
NavigationStack(path: $navPath) {
List {
ForEach(places, id: \.self) { place in
NavigationLink(value: place) {
HStack {
//place.image
Image("image")
.resizable()
.frame(width: 50, height: 50)
Text(place)
Spacer()
}
}
}
}
.navigationTitle("Places")
.navigationDestination(for: String.self) { place in
Text("Detail screen \(place)")
}
}
}
}
ADDED: Version with model as EnvironmentObject
class ViewModel: ObservableObject {
@Published var navPath: [String] = []
@Published var tabSelection: Int = 0
@Published var places = ["Paris", "Rome", "Berlin", "London", "Madrid", "Oslo"]
}
struct ContentView: View {
@StateObject var vm = ViewModel()
var body: some View {
TabView(selection: $vm.tabSelection) {
FirstScreen()
.tabItem {
Label("Selection", systemImage: "mappin.circle.fill")
}
.tag(0)
PlacesList()
.tabItem {
Label("Places", systemImage: "tray.2.fill")
}
.tag(1)
}
.environmentObject(vm)
}
}
struct FirstScreen: View {
@EnvironmentObject var vm: ViewModel
@State private var pickerChoice: String = "Rome"
var body: some View {
NavigationStack {
Form {
VStack {
Picker("Places", selection: $pickerChoice) {
ForEach(vm.places, id: \.self) { place in
Text(place)
.tag(place)
}
}
.pickerStyle(WheelPickerStyle())
Button {
vm.navPath = [pickerChoice]
vm.tabSelection = 1
} label: {
Text("Show place")
.font(.system(size: 20))
.padding()
.foregroundColor(.white)
.background(Color.blue)
.cornerRadius(8)
}
}
}
.navigationTitle("First Screen")
}
}
}
struct PlacesList: View {
@EnvironmentObject var vm: ViewModel
var body: some View {
NavigationStack(path: $vm.navPath) {
List {
ForEach(vm.places, id: \.self) { place in
NavigationLink(value: place) {
HStack {
//place.image
Image("image")
.resizable()
.frame(width: 50, height: 50)
Text(place)
Spacer()
}
}
}
}
.navigationTitle("Places")
.navigationDestination(for: String.self) { place in
Text("Detail screen \(place)")
}
}
}
}
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments