Skip to content
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

Offline Directions errors-clarification #2374

Merged
merged 4 commits into from
Jul 16, 2020
Merged

Conversation

Udumft
Copy link
Contributor

@Udumft Udumft commented May 27, 2020

Resolves #2273
Added new error case for indicating incorrect offline router object handling.

I hope I got original idea, described in the linked issue correctly...

What is the correct way of adding new localizations here? How can I add OFFLINE_CANCELLED translation and verify that it's correct?

@Udumft Udumft added bug Something isn’t working user: support labels May 27, 2020
@Udumft Udumft requested a review from 1ec5 May 27, 2020 09:54
@Udumft Udumft self-assigned this May 27, 2020
return
}

guard result.isSuccess else {
DispatchQueue.main.async {
completionHandler(session, .failure(.noData))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seem like .noData is not the correct option here. result has only 2 properties exposed: isSuccess (which is so far was unused) and json (which may contain a valid response or an error message). In current implementation, I struggle to find a correct definition of "router returned no data" case to fire .noData message.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This return value is a holdover from 0486778. It might be fine to reuse .noData for the .cancelled case. In the event of a failure, there should be an error that we can pass along.

@@ -196,6 +203,13 @@ public class NavigationDirections: Directions {

NavigationDirectionsConstants.offlineSerialQueue.async { [weak self] in
guard let result = self?.navigator.getRouteForDirectionsUri(url.absoluteString) else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per #2273 (comment), the only error case we should handle up here would be that self (NavigationDirections) has been deallocated.

Upon closer inspection, I’m wondering if it’s even appropriate to call the completion handler in this case. For mapbox/mapbox-gl-native-ios#210 mapbox/mapbox-gl-native-ios#200 (comment), we found that calling the completion handler after self has gone away forces the caller to consider whether self has gone away because the parent view controller has gone away or the application is terminating.

In other words, when an application calls this method from a MapViewController that holds a strong reference to NavigationDirections, does it expect the completion handler to magically be called even if that MapViewController has been deallocated (for example, because the user has exited that map screen to go to a different part of the application)? If the application has neglected to make self weak inside the completion handler, that could create other unexpected behavior in the application. The completion handler would have to explicitly handle the .cancelled case, so at least we would have to document that postcondition on the method, which is unfortunate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not calling a completion under some conditions may also lead to unexpected behavior. At least such use case must also be documented so that users are aware that completion call is not guaranteed.
Also, if we choose not to rise an explicit error message when NavigationDirections were deallocated, noData error becomes unused, so we can safely remove it

/**
The router did not finish the request
*/
case cancelled
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazingly, Apple can’t decide whether it should be “canceled” or “cancelled”. Either is fine here. 🤷‍♂️

@@ -34,6 +39,8 @@ public enum OfflineRoutingError: LocalizedError {
switch self {
case .standard(let error):
return error.localizedDescription
case .cancelled:
return NSLocalizedString("OFFLINE_CANCELLED", bundle: .mapboxCoreNavigation, value: "Routing was cancelled before response could be acquired.", comment: "Error description when Offline Router was deallocated before receiving the API response")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are some instructions for adding user-facing text to the SDK. The only remaining step would be to run scripts/extract_localizable.sh to add this string to a strings file.

return
}

guard result.isSuccess else {
DispatchQueue.main.async {
completionHandler(session, .failure(.noData))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This return value is a holdover from 0486778. It might be fine to reuse .noData for the .cancelled case. In the event of a failure, there should be an error that we can pass along.

@Udumft Udumft force-pushed the 2273-errors-clarification branch from d897f7c to 7a83226 Compare June 1, 2020 12:37
@Udumft Udumft marked this pull request as ready for review June 1, 2020 13:26
@Udumft Udumft requested a review from 1ec5 June 1, 2020 13:26
@Udumft Udumft requested a review from MaximAlien June 9, 2020 13:59
@@ -174,7 +166,7 @@ public class NavigationDirections: Directions {

- parameter options: A `RouteOptions` object specifying the requirements for the resulting routes.
- parameter offline: Determines whether to calculate the route offline or online.
- parameter completionHandler: The closure (block) to call with the resulting routes. This closure is executed on the application’s main thread.
- parameter completionHandler: The closure (block) to call with the resulting routes. This closure is executed on the application’s main thread. If called `NavigationDirections` instance is deallocated before route calculation is finished - completion won't be called.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not familiar with context of this problem, so just minor comment from me: probably better to limit length of lines to around 100-120, just for better readability.

@Udumft Udumft merged commit f2f78ce into master Jul 16, 2020
@Udumft Udumft deleted the 2273-errors-clarification branch July 16, 2020 09:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn’t working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Misleading guard statement in NavigationDirections.calculate(_:)
3 participants