Migrating selection-based navigation inside ForEach

Below is my deprecated solution to immediately go the the destination view when creating a new item with the "plus"-Button. I don't get how to migrate the deprecated 'init(destination:tag:selection:label:)' to the new NavigationStack or NavigationSplitView

Any help appreciated.

struct ItemList: View {
  @StateObject private var itemStore = ItemStore()
  @State private var indexItem: Int?
  var body: some View {
    NavigationView {
      List {
        let itemStoreZip = zip(itemStore.allItems.indices,
                               itemStore.allItems)
        ForEach(Array(itemStoreZip), id: \.0) {i, item in
          let itemBind = $itemStore.allItems[i]
          NavigationLink(destination: ItemDetail(item: itemBind),
                   tag: i,
                   selection: $indexItem) {
            ItemRow(item: item)
          }
        }
        
        .onDelete { indexSet in
          itemStore.removeItem(indexSet: indexSet)
        }
        .onMove { indices, newOffset in
          itemStore.moveItem(source: indices, to: newOffset)
        }
      }
      .navigationTitle("Homepwner")
      .toolbar {
        ToolbarItem(placement: ToolbarItemPlacement.navigationBarTrailing) {
          EditButton()
        }
        ToolbarItem(placement: ToolbarItemPlacement.navigationBarLeading) {
          Button {
            (indexItem,_) = itemStore.newItem()
          } label: {
            Image(systemName: "plus")
          }
        }
      }
    }
  }
}

Finally figured it out myself, if you see any possible improvement of my code I am happy to learn :-)

struct ItemList: View {

    @StateObject private var itemStore = ItemStore()

    @State private var newItem = false

    @State private var indexItem: Int?

    var body: some View {

        NavigationStack() {

            List {

                let itemStoreZip = zip(itemStore.allItems.indices, itemStore.allItems)

                ForEach(Array(itemStoreZip), id: \.0) {i, item in

                    let itemBind = $itemStore.allItems[i]

                    NavigationLink {

                        ItemDetail(item: itemBind)

                    } label: {

                        ItemRow(item: item)

                    }

                    

                }

                .onDelete { indexSet in

                    itemStore.removeItem(indexSet: indexSet)

                }

                .onMove { indices, newOffset in

                    itemStore.moveItem(source: indices, to: newOffset)

                }

            }

            .navigationDestination(isPresented: $newItem) {

                if let indexItem {

                    ItemDetail(item: $itemStore.allItems[indexItem])

                }

            }

            .navigationTitle("Homepwner")

            .toolbar {

                ToolbarItem(placement: ToolbarItemPlacement.navigationBarTrailing) {

                    EditButton()

                }

                ToolbarItem(placement: ToolbarItemPlacement.navigationBarLeading) {

                    Button {

                        (indexItem,_) = itemStore.newItem()

                        newItem = true

                    } label: {

                        Image(systemName: "plus")

                    }

                }

            }

        }

    }

}

Deprecated does not mean it does not work anymore.

I advise you to keep NavigationView for the time being, because NavigationStack works only for iOS 16. So you would have to create different code parts for older versions of iOS.

So, wait until iOS 16 is widely adopted, then use NavigationStack (which is very simple to use):

  • you can simply replace NavigationView by NavigationStack. Doesn't it work ?
  • or change as described in doc:
NavigationStack {
    List(parks) { park in
        NavigationLink(park.name, value: park)
    }
    .navigationDestination(for: Park.self) { park in
        ParkDetails(park: park)
    }
}
Migrating selection-based navigation inside ForEach
 
 
Q