Learn Courses My Dashboard

Move Items in a NavigationLink

I am attempting to call a move() method to move the order of a NavigationList in a NavigationView. I can’t figure out how to make each Links line identifiable. I have seen ForEach used that builds a List and gives each an id: but my code is a bit different. Any guidance in the right direction to help my studies would be great. Much appreciated.

I keep getting errors:

Next to the .onMove:
Value of type ‘NavigationLink<HStack<TupleView<(some View, Text)>>, DetailView>’ has no member ‘onMove’

Next to the function:
Cannot call value of non-function type ‘Binding’

Value of type ‘ObservedObject.Wrapper’ has no dynamic member ‘move’ using key path from root type ‘TitleModel’

…with the following code:

import SwiftUI

struct MyFlightView: View {
    
    //reference the view model
    @ObservedObject var model = TitleModel()
    
    var body: some View {
        
        NavigationView {
            List(model.titles) { title in
                
                NavigationLink(destination: DetailView(detail: title),
                    label: {
                        
                        HStack(spacing: 20.0) {
                            Image(title.image1)
                            .resizable()
                            .scaledToFill()
                            .frame (width: 50, height: 50, alignment: .center)
                            .clipped()
                            .cornerRadius(5)
                            Text(title.title)
                        }
                    })
                
                .onMove(perform: move)
                
            }
            .toolbar {
                EditButton()
            }
            .navigationBarTitle("MyFlight")
        }
    }
    
    func move(from source:IndexSet, to destination: Int) {
        $model.move(fromOffsets: source, toOffsets: destination)
    }
}

struct MyFlightView_Previews: PreviewProvider {
    static var previews: some View {
        MyFlightView()
    }
}

Instead of this:

List(model.titles) { title in
    
    NavigationLink(destination: DetailView(detail: title),
        label: {
            
            HStack(spacing: 20.0) {
                Image(title.image1)
                .resizable()
                .scaledToFill()
                .frame (width: 50, height: 50, alignment: .center)
                .clipped()
                .cornerRadius(5)
                Text(title.title)
            }
        })
    
    .onMove(perform: move)
    
}

do this:

List {
    ForEach(model.titles) { title in
        NavigationLink(destination: DetailView(detail: title),
            label: {
            
                HStack(spacing: 20.0) {
                    Image(title.image1)
                    .resizable()
                    .scaledToFill()
                    .frame (width: 50, height: 50, alignment: .center)
                    .clipped()
                    .cornerRadius(5)
                    Text(title.title)
                }
            })
    }
    .onMove(perform: move)
}

onMove(perform:) is not available on List or NavigationLink. It is available on Views that conform to the DynamicViewContent protocol, which ForEach does.

Good morning roosterboy. That explains the ForEach that kept popping up in all the videos I watched yesterday.

I am still having the issue with the func errors:

Cannot call value of non-function type ‘Binding’

Value of type ‘ObservedObject.Wrapper’ has no dynamic member ‘move’ using key path from root type ‘TitleModel’

Is this due to the ‘var model’ referencing my View Model? The examples I have been studying don’t reference a View Model like I am for my JSON.

Thanks again for the help and enjoy your day.

Cheers,
Shawn

I am thinking that I need to provide an id: to identify each line in the list so that when I call the .onMove function it will work. I tried this but it did not work.

ForEach(model.titles, id:\.self)

then added:

.onMove { (indexSet, index) in
   self.model.move(fromOffsets: indexSet, toOffset: index)
{

Fixed! Sometimes it is the obvious that stumps you I guess. Misspelled ‘toOffset’ and didn’t call the instance correctly.

    func move(from source:IndexSet, to destination: Int) {
        (model.titles).move(fromOffsets: source, toOffset: destination)
     }

Thanks again roosterboy!