7

I have a list of items. Clicking on one should push a new view to the navigation stack. I notice the NavigationLink doesn't work if the list is in edit mode. Is there a way to control that? I need it to work in edit mode.

List {
    ForEach(segments) { segment in
        NavigationLink(destination: EditSegmentView(segment: segment)) {
            Text(segment.title)
        }
    }.onDelete(perform: onDelete)
     .onMove(perform: onMove)
}.environment(\.editMode, $alwaysTrue)
Rob N
  • 15,024
  • 17
  • 92
  • 165
  • The link not working in edit mode is expected behaviour. If you imagine it from the user standpoint they would not want to be editing a list and accidentally navigate into one of the items they are editing. What is it you are actually trying to achieve by keeping it in edit mode? – Infinity James Oct 05 '19 at 09:25
  • 2
    I'm editing a list of exercises in a workout. You can add/remove/move exercises in the list, and you can also drill down to edit a particular exercise (changes it's name, duration, etc.) I'm porting from UITableView code. I thought the UI was okay before. The delete button and move handles are separate from the name text, which triggers the navigate. – Rob N Oct 05 '19 at 11:03
  • Arguably you are fighting upstream in trying to both activate edit mode and allow navigation. You should find a new way to achieve the desired UI. – Infinity James Oct 08 '19 at 09:23
  • I'll have to think about how I might redesign my app to work like that, but for now I just want to port parts of it to SwiftUI, if I can. I'm okay with being coaxed in a direction by a UI framework, but if SwiftUI is too restrictive I may not like it. For now, I have something working which I just posted in an answer. – Rob N Oct 08 '19 at 17:26
  • 3
    I don't think that's expected behaviour. apple's contacts app in iOS does what Rob N is trying to do – ngb Sep 14 '20 at 05:47

1 Answers1

9

I now have this working the way I wanted. I used a different NavigationLink initializer, with the tag and selection arguments. It seems to work well, but I don't know if this is the intended use of that initializer, because the documentation is painfully sparse.

@State var segmentSelection: Segment.ID? = nil

var body: some View {
    NavigationView {
        ...
        List {
            ForEach(workout.segments) { segment in
                NavigationLink(destination: EditSegmentView(segment: segment),    
                               tag: segment.id,
                               selection: self.$segmentSelection) {
                                Text(segment.title)
                }
                .onTapGesture(perform: { self.segmentSelection = segment.id })
            }.onDelete(perform: onDelete)
             .onMove(perform: onMove)
        }.environment(\.editMode, Binding.constant(.active))
        ...
    }
}
Rob N
  • 15,024
  • 17
  • 92
  • 165
  • is this line together with the selection and tag initialiser that makes this work:.onTapGesture(perform: { self.segmentSelection = segment.id }). can use it to make a custom picker too. thanks! – ngb Feb 06 '21 at 05:38