Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.
This repository was archived by the owner on Aug 8, 2023. It is now read-only.

Make iOS delegate notifications consistent with MapKit #2775

Closed

Description

@friedbunny

MapKit loading delegate callbacks are exclusively about fetching map data, while rendering ones are exclusively the drawing of the map.

The flow for Mapkit looks like this on initialization:

2015-10-23 19:39:28.470 start RENDERING
2015-10-23 19:39:28.503 start LOADING
2015-10-23 19:39:29.435 finish LOADING
2015-10-23 19:39:30.470 finish RENDERING fullyRendered: YES

Panning around continues to issue the same notification flow.

We don't follow MapKit conventions currently. Instead, at the core-level:

Our initialization flow looks like:

2015-10-23 19:42:21.695 start RENDERING
2015-10-23 19:42:24.260 finish RENDERING fullyRendered: YES
2015-10-23 19:42:24.262 finish LOADING

Panning around our map subsequently only sends more DidFinishRenderingMap, nothing else.

Making our iOS map delegate notifications consistent with MapKit will require core changes, rather than iOS changes, which will in turn affect Android. Should Android follow these conventions, too?

/cc @mapbox/mobile

Activity

  1. ljbade commented on Oct 24, 2015

    @ljbade
    Contributor

    For Android, the main concern is the loading/failed loading events are the only way to return an error about loading the style to the app since everything is async.

    @friedbunny How does iOS return async style load failures?

  2. friedbunny commented on Oct 24, 2015

    @friedbunny
    ContributorAuthor

    MapChangeDidFinishRenderingMapFullyRendered with a false value would indicate some tile(s) failed to render, while MapChangeDidFailLoadingMap would fire when map data failed to load from the network. Neither of these are implemented.

    We could also potentially use MapChangeDidFailLoadingMap to indicate that styles have failed to load. Currently, we throw somewhat cryptic errors from MapContext::setStyleURL — usually just the HTTP error code. I don't believe iOS has any direct way of knowing if a style has failed to load.

  3. ljbade commented on Oct 28, 2015

    @ljbade
    Contributor

    As for async style load failures, both iOS and Android are going to implement proper C++ exception handling for this in #2825

  4. 1ec5 commented on Oct 28, 2015

    @1ec5
    Contributor

    @ljbade, #2762 is the most likely way for this to be implemented in iOS, although we could take an approach similar to #2825 to turn exceptions into NSExceptions, which would result in a slightly improved experience. But #2825 is about Android, which needs this much more than iOS right now.

  5. 1ec5 commented on Mar 30, 2016

    @1ec5
    Contributor

    #4527 proposes an additional mbgl notification for when the style has finished loading that could be useful for MGLMapViewDelegate.

  6. added
    MapKit parityFor feature parity with MapKit on iOS or macOS
    on Aug 22, 2016
  7. lightandshadow68 commented on Jan 23, 2017

    @lightandshadow68

    It also appears the order in which mapView:didDeselectAnnotationView and mapView:didSelectAnnotationView is different. in MapKit, didDeselect is called first and then didSeselect. However, the opposite order is used with MGLMapView.

    For example, I show a UICollectionView when an annotation is tapped and hide it when a user taps on an empty area of the map. To accomplish this, I start a timer in didDeselect to hide the view, which is invalidated in didSelect. However, this strategy no longer works since didSelect is called first.

  8. lightandshadow68 commented on Jan 24, 2017

    @lightandshadow68

    Actually, it looks like update code called from my implementation of didSelectAnnotationView has started causing didDeselectAnnotationView to be called with Mapbox GL. So, it only appeared that the order had changed. I'll try to track down where the actual behavior differs. But, as of now, the order in which didSelect and didDeselect is called no longer appears to be where the difference lies.

  9. lightandshadow68 commented on Jan 25, 2017

    @lightandshadow68

    It looks like one of these two cases are causing mapView:didDeselectAnnotationView to be called when changing the region of the map via [MGLMapView showAnnotations:edgePadding:].

    case mbgl::MapChangeRegionWillChange:
            case mbgl::MapChangeRegionWillChangeAnimated:
            {
                if ( ! _userLocationAnnotationIsSelected
                    || self.userTrackingMode == MGLUserTrackingModeNone
                    || self.userTrackingState != MGLUserTrackingStateChanged)
                {
                    UIView<MGLCalloutView> *calloutView = self.calloutViewForSelectedAnnotation;
                    BOOL dismissesAutomatically = (calloutView
                                                   && [calloutView respondsToSelector:@selector(dismissesAutomatically)]
                                                   && calloutView.dismissesAutomatically);
                    // dismissesAutomatically is an optional property and we want to dismiss
                    // the callout view if it's unimplemented.
                    if (dismissesAutomatically || ![calloutView respondsToSelector:@selector(dismissesAutomatically)])
                    {
                        [self deselectAnnotation:self.selectedAnnotation animated:NO];
                    }
                    else
                    {
                        // Deselect annotation if it lies outside the viewport
                        if (self.selectedAnnotation) {
                            MGLAnnotationTag tag = [self annotationTagForAnnotation:self.selectedAnnotation];
                            MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(tag);
                            MGLAnnotationView *annotationView = annotationContext.annotationView;
                            
                            CGRect rect = [self positioningRectForCalloutForAnnotationWithTag:tag];
                            
                            if (annotationView)
                            {
                                rect = annotationView.frame;
                            }
                            
                            if ( ! CGRectIntersectsRect(rect, self.frame)) {
                                [self deselectAnnotation:self.selectedAnnotation animated:NO];
                            }
                        }
                    }
                }
    
                if ( ! [self isSuppressingChangeDelimiters] && [self.delegate respondsToSelector:@selector(mapView:regionWillChangeAnimated:)])
                {
                    BOOL animated = change == mbgl::MapChangeRegionWillChangeAnimated;
                    [self.delegate mapView:self regionWillChangeAnimated:animated];
                }
                break;
            }
    

    When tapping on an annotation that is in the center of the screen, and remains there throughout the region change, the annotation is still deselected. I'm not sure if the viewport check or callout deselection is being incorrectly triggered.

    I attempted to set a flag in my delegate to ignore the deselection callback when the region is changing, but deselection occurs before regionWillChangeAnimated is called.

  10. stale commented on Nov 24, 2018

    @stale

    This issue has been automatically detected as stale because it has not had recent activity and will be archived. Thank you for your contributions.

  11. reopened this on Nov 30, 2018
  12. removed
    archivedArchived because of inactivity
    on Nov 30, 2018
  13. stale commented on May 29, 2019

    @stale

    This issue has been automatically detected as stale because it has not had recent activity and will be archived. Thank you for your contributions.

  14. removed
    archivedArchived because of inactivity
    on May 29, 2019
  15. stale commented on May 22, 2020

    @stale

    This issue has been automatically detected as stale because it has not had recent activity and will be archived. Thank you for your contributions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    MapKit parityFor feature parity with MapKit on iOS or macOSarchivedArchived because of inactivitybuggl-iosiOSMapbox Maps SDK for iOSmacOSMapbox Maps SDK for macOSrefactor

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions