1

Let say you are loading some data from network when you are at screen A that it takes sometime. While you are waiting you can navigate to other screens by using NavigationLink. So, at the moment you are at the screen B then the data from network is finished loading and send value back to datasource in screen A. The NavigationView pop itself automatically so you back to screen A by unintentionally. Do you have any idea? Thanks.

Example

struct ContentView: View {
  @ObservedObject var viewModel = ViewModel()
  
  var body: some View {
    NavigationView {
      List(viewModel.dataSource, id: \.self) { item in
        NavigationLink(destination: Text("\(item)")) {
          Text("\(item)")
            .padding()
        }
      }
    }
  }
}

class ViewModel: ObservableObject {
  @Published private(set) var dataSource = [1, 2, 3, 4, 5]
  
  init() {
    DispatchQueue.main.asyncAfter(deadline: .now() + 3) { // simulate calling webservice
      self.dataSource[0] = 99
    }
  }
}
itopstory
  • 33
  • 2
  • 4
  • Does this answer your question? [SwiftUI ForEach refresh makes view pop](https://stackoverflow.com/questions/61987960/swiftui-foreach-refresh-makes-view-pop) – Simon Aug 20 '21 at 11:55
  • just remove this line `self.dataSource[0] = 99` and update in any variable . This wont update Screen and wont pop you back to firstVC. – Kudos Aug 20 '21 at 11:58

1 Answers1

0

This happens because you're specifying id as item itself, and when list updated there's no original item anymore, so it closes

If you just wanna modify items without adding/removing/reordering, you can make index your item id:

NavigationView {
    List(viewModel.dataSource.indices, id: \.self) { i in
        let item = viewModel.dataSource[i]
        NavigationLink(destination: Text("\(item)")) {
            Text("\(item)")
                .padding()
        }
    }
}

But with more complex data you need to have your items Identifiable with unique ids, and you won't have such problem. Check out this example:

struct ContentView: View {
    @ObservedObject var viewModel = ViewModel()
    
    var body: some View {
        NavigationView {
            List(viewModel.dataSource) { item in
                NavigationLink(destination: Text("\(item.value)")) {
                    Text("\(item.value)")
                        .padding()
                }
            }
        }
    }
}

class ViewModel: ObservableObject {
    @Published private(set) var dataSource: [Item] = [1, 2, 3, 4, 5]
    
    init() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [self] in // simulate calling webservice
            // you're modifying value but id stays the same
            self.dataSource[0].value = 99
        }
    }
}

struct Item: Identifiable, ExpressibleByIntegerLiteral {
    let id = UUID()
    var value: Int
    
    init(integerLiteral value: IntegerLiteralType) {
        self.value = value
    }
}
Phil Dukhov
  • 67,741
  • 15
  • 184
  • 220