Search code examples
foreachswiftuiuipageviewcontrollerswiftui-listswiftui-navigationlink

SwiftUI - trying to identify and pass the value of the list item being selected


I'm following the Apple Developer tutorial on interfacing with UIKIt

The only real difference is that that I'm trying to call

PageView<Page:View> { 

from a NavigationLink. The example code within PageView has a default value hardcoded of

@State var currentPage = 0 

I'd rather initiate the swipe process on the view that the user selected and not start at the first one and I'm trying to create a simple way to swipe through the items without having to return to the navigationlink to access the next item on the list.

Is there a way to trap the index of the link the user selected and pass this through to PageView as a variable.

I'd tried incrementing a counter and using a function to increment the counter and return the PageView sruct without any success. animals is an array, just in case that wasn't clear and I'm using the map function to pass in the appropriate value to create the detailed view I'm looking to create . Also, I realize I could probably put the detail view in a scroll view.

Here's my code

var body: some View {
    List {
        ForEach(collection.animals, id: \.self) { animal in
            NavigationLink(destination:PageView(self.collection.animals.map { AnimalDetail(animalMetadata: $0.wrappedMetadata  )})) {
            AnimalRow(thumbnailImage: Image(uiImage: UIImage(data: animal.image!)!), label: (animal.name!) ).font(.subheadline)
            
         }
    }.onDelete(perform: delete)
}

Everything else seems to work fine - just can't figure a way to capture an index value from the list to indicate which item/view was clicked and to pass that value through to PageView in order to create this as the first viewed View.

Thank you !

edit

I tried using .enumerated() on the Array but still couldn't figure out how to get the specific index value to the PAgeView view.

    List {
        ForEach(Array(collection.animals.enumerated()), id: \.1.id) {index, item in
            NavigationLink(destination:PageView( self.collection.animals.map { AnimalDetail(animalMetadata: $0.wrappedMetadata)} )) {
            AnimalRow(thumbnailImage: Image(uiImage: UIImage(data: item.image!)!), label: (animal.name!) ).font(.subheadline)
                
    }
}.onDelete(perform: delete)

Solution

  • Try the following...

    In PageView:

    struct PageView<Page: View>: View {
        var viewControllers: [UIHostingController<Page>]
        @State var currentPage: Int // no initial value
    
        init(_ views: [Page], selection: Int) {
            _currentPage = State(initialValue: selection)
            self.viewControllers = views.map { UIHostingController(rootView: $0) }
        }
    
        // ... other code here
    }
    

    In your code:

    var body: some View {
        List {
            ForEach(Array(collection.animals.enumerated()), id: \.element) { idx, animal in
                NavigationLink(destination: 
                  PageView(self.collection.animals.map { 
                      AnimalDetail(animalMetadata: $0.wrappedMetadata  )}, 
                      selection: idx)) {     // << here !!
    
                  AnimalRowRow(thumbnailImage: Image(uiImage: UIImage(data: animal.image!)!), 
                      label: (animal.name!) ).font(.subheadline)
                
             }
        }.onDelete(perform: delete)
    }