9

This is how the crash looks like

enter image description here

So it randomly crashes on the UIKit line

UIKitCore
-[UIViewController _ancestorViewControllerOfClass:allowModalParent:] + 44

I have View in default SwiftUI navigation stack:

struct MyView: View {
  @EnvironmentObject var viewModel: MyViewModel
  @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

var body: some View {
    ZStack {
      ......
    }
    .onAppear {
      self.viewModel
        .onViewAppear(presentationMode: self.presentationMode)
    }
  }
}

final class MyViewModel {
  var presentationMode: Binding<PresentationMode>?

  func onViewAppear(presentationMode: Binding<PresentationMode>) {
    self.presentationMode = presentationMode
  }

  func hide() {
    presentationMode?.wrappedValue.dismiss() // crashes after calling this
  }
}

So I push MyView in navigation stack this way:

NavigationLink(
      destination: MyView()
    ) {
      Image(systemName: "plus.circle")
        .font(.title)
    }

And then after user presses a button in MyView after several seconds I call hide() in the MyViewModel. Almost all the time it works but in 5-10% cases it crashes.

Paul T.
  • 4,938
  • 7
  • 45
  • 93
  • Not sure what button you mean, but actually in MyViewModel I just load data from backend, display it and have DispatchQueue.main.asyncAfter(.now + 1) { self.hide() } – Paul T. Jul 28 '20 at 13:52
  • "after user presses a button in MyView - this button" as I told in a comment above. After pressing that button I just call a viewModel.buttonPressed(). Then view model loads this data from backend and then on the main queue ViewModels calls hide – Paul T. Jul 28 '20 at 14:32
  • " Why don't you call presentationMode?.wrappedValue.dismiss() directly in view? " Because I decide that I need to hide the view in the view model, because I need to hide the view after I got response from backend. – Paul T. Jul 28 '20 at 14:33
  • "This transfer via view model looks strange for me" - it's a responsibility of a view model to hide the screen. Not the view. "If it happens that view is recreated (due to some parent refresh) then binding in view model might become dangling" - if view is recreated, the view model will be recreated too, because view is created with a Builder that builds a view model too – Paul T. Jul 28 '20 at 14:36
  • Do you need to add `MyView().environmentObject(viewModel)`? Seems like the view model wouldn't be set in that initialiser. – Pranav Kasetti Aug 03 '20 at 17:49
  • Is it possible that the user closes the modal before you automatically hide it? – Pranav Kasetti Aug 03 '20 at 18:04
  • @PranavKasetti in will be set. Even more, before hiding this view model start network request after View Appear, so 100% it is initialized – Paul T. Aug 04 '20 at 02:32
  • @PranavKasetti nope, it crashes without any actions from User. User just waits – Paul T. Aug 04 '20 at 02:32
  • how do you know that? the user could be clicking the back button on the nav bar! – Pranav Kasetti Aug 04 '20 at 14:40
  • @PranavKasetti I know because I can see the crash on my device, I can reproduce it from time to time – Paul T. Aug 04 '20 at 15:47
  • Ok. Just for testing, do you get the same crash if you use `@StateObject` instead of `@EnvironmentObject`? Maybe worth a try, this definitely seems like a SwiftUI bug though! – Pranav Kasetti Aug 04 '20 at 18:29
  • @PranavKasetti I have never used StateObject , could you please give an example instead of Environment(\.presentationMode) ? – Paul T. Aug 05 '20 at 02:30
  • Change `@EnvironmentObject var viewModel: MyViewModel` to `@StateObject var viewModel: MyViewModel = MyViewModel()` – Pranav Kasetti Aug 05 '20 at 14:42
  • sure, I'll try and write back here, but in my opinion the issue is with @Environment(\.presentationMode) var presentationMode: Binding somehow – Paul T. Aug 06 '20 at 02:35
  • Any news about this? I'm also having this problem @PaulT. – zgluis Sep 21 '20 at 14:30

1 Answers1

1

Fix for me was to set .navigationViewStyle(StackNavigationViewStyle())

NavigationView { content }.navigationViewStyle(StackNavigationViewStyle())

druid_sf
  • 51
  • 4