lostintranslation
lostintranslation

Reputation: 24583

Custom button to track MKUserTrackingMode

I am trying to implement a custom button to track the MKUserTrackingMode. I know there is a MKUserTrackingBarButtonItem however I cannot user that because my button is not in a toolbar/navbar, so I am stuck implementing my own logic.

Basically I want the same logic as the MKUserTrackingBarButtonItem provides but I am having a really hard time implementing that. Basically if in MKUserTrackingModeNone and the button is clicked move to MKUserTrackingModeFollow with animation. This is where my problem arises, if the map is animated while switches this state I do not want the user to be able to get to the next state MKUserTrackingModeFollowWithHeading. IE user will have to wait until the map animation is complete and the user is centered in the mapview to be able to move to the MKUserTrackingModeFollowWithHeading state. Mainly my problem is trying to detect when the mapview is done animating.

I have implemented:

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
    self.isTrackingAnimation = NO;
}

So when my map animation stops I set a flag to give me an indication that I am no longer animating.

I have tried to implement a method that can determine if the state can be switched.

- (BOOL) setUserTrackingMode:(MKUserTrackingMode) mode {
    if (self.isTrackingAnimation && mode == MKUserTrackingModeFollowWithHeading) return NO;

    return YES;
}

- (IBAction)onTrackingButtonPressed:(id)sender {
    switch (self.mapView.userTrackingMode) {
        case MKUserTrackingModeNone: {
            if ([self canSetUserTrackingMode:MKUserTrackingModeFollow]) {
                [self.trackingButton setImage:[UIImage imageNamed:@"location_arrow_on.png"] forState:UIControlStateNormal];
                [self.mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
                self.isTrackingAnimation = YES;

            }

            break;
        };
        case MKUserTrackingModeFollow: {
            if ([self canSetUserTrackingMode:MKUserTrackingModeFollowWithHeading]) {
                [self.trackingButton setImage:[UIImage imageNamed:@"location_arrow_follow.png"] forState:UIControlStateNormal];
                [self.mapView setUserTrackingMode:MKUserTrackingModeFollowWithHeading animated:YES];

            }

            break;
        };
        case MKUserTrackingModeFollowWithHeading: {
            if ([self canSetUserTrackingMode:MKUserTrackingModeNone]) {
                [self.trackingButton setImage:[UIImage imageNamed:@"location_arrow_off.png"] forState:UIControlStateNormal];
                [self.mapView setUserTrackingMode:MKUserTrackingModeNone animated:YES];

            }

            break;
        }
    }
}

Problem arises when I switch the state a few times such that a transition from MKUserTrackingModeNone to MKUserTrackingModeFollow does not actually animate the map since the map is already centered on the users location. I.E. I say that I am going to track user with animation so I set self.isTrackingAnimation = YES; but it never gets set to NO because the map never actually animates.

IE if I had a completion block on [self.mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES]; and that completion block did not fire until the map had animated (or not if it did not need to animate) I would be fine.

Only other thing I can think to do is check if the map actually needs to animate when setting the usertrackingmode, if it does not need to animate I can not set the self.isTrackingAnimation.

Ideas?

Upvotes: 1

Views: 1099

Answers (2)

incanus
incanus

Reputation: 5128

You may want to go the route of KVO, to observe the actual property change on the map view. We did this in our own bar button item that was tied to a map view in an SDK we built — not MapKit, but the same idea (an open source version of MapKit).

https://github.com/mapbox/mapbox-ios-sdk/blob/release/MapView/Map/RMUserTrackingBarButtonItem.m

See specifically the watching of the map view:

https://github.com/mapbox/mapbox-ios-sdk/blob/509fa7df46ebd654d130ab2f530a8e380bf2bd59/MapView/Map/RMUserTrackingBarButtonItem.m#L153-L155

And the acting on changes:

https://github.com/mapbox/mapbox-ios-sdk/blob/509fa7df46ebd654d130ab2f530a8e380bf2bd59/MapView/Map/RMUserTrackingBarButtonItem.m#L177

Upvotes: 0

Paulw11
Paulw11

Reputation: 115041

Rather than setting self.isTrackingAnimation = YES; in your button press handler, you should implement the delegate method regionWillChangeAnimated: and set the flag there.

Upvotes: 1

Related Questions