-
Notifications
You must be signed in to change notification settings - Fork 318
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Crash presenting generic shield in SwiftUI — unwrapped nil in InstructionPresenter.swift #2300
Comments
@zacharyblank, are you developing the application in SwiftUI, by any chance? The line that’s crashing was originally introduced in #1272:
The containing method, The crash means either the application has no application delegate (unlikely) or the application delegate has no window. With SwiftUI, the scene delegate holds onto the window instead of the application delegate. A short-term fix would be for As for a better fix that preserves the capsule-like appearance, I don’t see a straightforward way to get the current window through the current scene, as we can through UIApplication with a conventional UI. Perhaps it wouldn’t be too weird to crawl up the responder chain looking for a window. But that would still require access to a view that’s already in the window’s view hierarchy. InstructionPresenter converts a visual instruction into an attributed string and respond to image downloads by replacing them in the string. As a standalone class, it’s designed to abstract away that job from any views. The fact that it internally reaches right out to the UIApplication’s main window demonstrates that this abstraction isn’t particularly useful. Moreover, InstructionPresenter is only used by #2275 already rewrote a large portion of InstructionPresenter to make it more intuitive, portable, and reusable. I think we should eliminate InstructionPresenter and split its functionality between extensions on /cc @mapbox/navigation-ios |
That is 100% right. SwiftUI. Thanks for the detailed explanation. It makes sense. I can fork and do the quick fix as you recommended and/or I can wait for the better fix as you described depending on timing. What is the update cycle like? Thanks again! |
A PR with the quick fix would be great. We’re currently in the middle of the v1.0 release cycle, which will take a while longer. We just put out a first alpha and are planning to put out a second alpha in the next week or two. In the meantime, you’re welcome to have your project depend on the master branch if that would unblock your development efforts. We might also consider cherry-picking the fix into the release-v0.38 branch and releasing v0.38.3 with it if we need the fix to go into a stable release sooner. |
@1ec5 I'm afraid that, in fact, didn't seem to be the issue. I simply returned |
I’m able to reproduce this issue with the following code: ContentView.swiftimport SwiftUI
import MapboxDirections
import MapboxCoreNavigation
import MapboxNavigation
import Combine
class RouteCalculator: ObservableObject {
@Published var route: Route?
func calculate(_ options: RouteOptions) {
Directions.shared.calculate(options) { [weak self] (waypoints, routes, error) in
self?.route = routes?.first
}
}
}
struct NavigationView: UIViewControllerRepresentable {
typealias UIViewControllerType = NavigationViewController
@Environment(\.presentationMode) var presentationMode
var route: Route
class Coordinator: NavigationViewControllerDelegate {
var parent: NavigationView
init(_ parent: NavigationView) {
self.parent = parent
}
func navigationViewControllerDidDismiss(_ navigationViewController: NavigationViewController, byCanceling canceled: Bool) {
parent.presentationMode.wrappedValue.dismiss()
}
}
func makeCoordinator() -> NavigationView.Coordinator {
return Coordinator(self)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<NavigationView>) -> NavigationViewController {
let viewController = NavigationViewController(for: route)
viewController.modalPresentationStyle = .fullScreen
viewController.delegate = context.coordinator
return viewController
}
func updateUIViewController(_ uiViewController: NavigationViewController, context: UIViewControllerRepresentableContext<NavigationView>) {
}
}
struct ContentView: View {
@ObservedObject private var routeCalculator = RouteCalculator()
init() {
let origin = Waypoint(coordinate: CLLocationCoordinate2D(latitude: 45.5476633, longitude: -122.6624749))
let destination = Waypoint(coordinate: CLLocationCoordinate2D(latitude: 45.5189373, longitude: -122.6771381))
let options = NavigationRouteOptions(waypoints: [origin, destination])
routeCalculator.calculate(options)
}
var body: some View {
if let route = routeCalculator.route {
return AnyView(NavigationView(route: route))
} else {
return AnyView(Text("Loading…"))
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
} The issue reproduces on launch but only with these specific coordinates; I don’t reproduce the issue simulating a route in other cities. |
In fact, mapbox-navigation-ios/MapboxNavigation/NavigationViewController.swift Lines 283 to 286 in d70618e
/cc @JThramer |
I'm using version 0.38.1. I'm in Portland Oregon and certain routes always cause a crash with the error:
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
in
InstructionPresenter.swift
on line236
.The coordinates I use that for sure give me a crash are:
from:
45.5476633, -122.6624749
to:
45.5189373, -122.6771381
I assume there is something in the JSON response for one of the instructions along this route and other routes in Portland that include the same instruction but I cannot hunt it down. Please help.
Most other routes work just fine.
Thank you!
The text was updated successfully, but these errors were encountered: