在放大时使用MKMapView在setUserTrackingMode上崩溃

时间:2013-05-17 20:42:06

标签: ios objective-c mapkit core-location

我有带MKUserTrackingModeFollowWithHeading的MKMapView。 但有些东西会将userTrackingMode更改为MKUserTrackingModeFollow或None, 所以我实施了,

- (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated
{
    if ([CLLocationManager locationServicesEnabled]) {
        if ([CLLocationManager headingAvailable]) {
            [self.myMapView setUserTrackingMode:MKUserTrackingModeFollowWithHeading animated:NO];
        }else{
            [self.myMapView setUserTrackingMode:MKUserTrackingModeFollow animated:NO];
        }
    }else{
        [self.myMapView setUserTrackingMode:MKUserTrackingModeNone animated:NO];
    }
}

一切都很好,但每当我将地图放大到最详细程度时,应用程序会在上面显示的行setUserTrackingMode:MKUserTrackingModeFollowWithHeading中导致EXC_BAD_ACCESS。

我应该怎么做才能避免崩溃?如果可能,我不想使用MKUserTrackingBarButtonItem。

mapViewController的另一部分位于下方。

- (void)dealloc
{
    self.myMapView.delegate = nil;
}

- (void)viewWillDisappear:(BOOL)animated
{
    if ([CLLocationManager locationServicesEnabled]) {
        self.myMapView.showsUserLocation = NO;
        [_locManager stopUpdatingLocation];

        if ([CLLocationManager headingAvailable]) {
            [_locManager stopUpdatingHeading];
        }
    }

    [super viewWillDisappear:animated];
}

- (void)viewDidAppear:(BOOL)animated
{
    if ([CLLocationManager locationServicesEnabled]) {
        self.myMapView.showsUserLocation = YES;
        [_locManager startUpdatingLocation];

        if ([CLLocationManager headingAvailable]) {
            [self.myMapView setUserTrackingMode:MKUserTrackingModeFollowWithHeading animated:NO];
            [_locManager startUpdatingHeading];
        }else{
            [self.myMapView setUserTrackingMode:MKUserTrackingModeFollow animated:NO];
        }
    }else{
        [self.myMapView setUserTrackingMode:MKUserTrackingModeNone animated:NO];
    }
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    self.myMapView.delegate = self;
    [self.myMapView setFrame:self.view.frame];

    self.locManager = [CLLocationManager new];
    [self.locManager setDelegate:self];
    [self.locManager setDistanceFilter:kCLDistanceFilterNone];
    [self.locManager setDesiredAccuracy:kCLLocationAccuracyBest];
    [self.locManager setHeadingFilter:3];
    [self.locManager setHeadingOrientation:CLDeviceOrientationPortrait];
}

任何建议都表示赞赏。提前谢谢。

我将最低样本代码上传到github

2 个答案:

答案 0 :(得分:3)

我可能会建议尝试推迟跟踪模式的设置,例如:

- (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated
{
    dispatch_async(dispatch_get_main_queue(),^{
        if ([CLLocationManager locationServicesEnabled]) {
            if ([CLLocationManager headingAvailable]) {
                [self.myMapView setUserTrackingMode:MKUserTrackingModeFollowWithHeading animated:NO];
            }else{
                [self.myMapView setUserTrackingMode:MKUserTrackingModeFollow animated:NO];
            }
        }else{
            [self.myMapView setUserTrackingMode:MKUserTrackingModeNone animated:NO];
        }
    });
}

我可能还建议您检查以确保mode不是您想要的,从而消除了多余的setUserTrackingMode

- (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated
{
    MKUserTrackingMode newMode = MKUserTrackingModeNone;

    if ([CLLocationManager locationServicesEnabled]) {
        if ([CLLocationManager headingAvailable]) {
            newMode = MKUserTrackingModeFollowWithHeading;
        }else{
            newMode = MKUserTrackingModeFollow;
        }
    }

    if (mode != newMode)
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.myMapView setUserTrackingMode:newMode animated:YES];
        });
    }
}

您还可以将其与scrollEnabled结合使用(这可以防止用户偶然启动更改跟踪模式)。

答案 1 :(得分:-1)

Swift 3

func mapView(_ mapView: MKMapView, didChange mode: MKUserTrackingMode, animated: Bool) {        
        var newMode: MKUserTrackingMode = .none
        if ( CLLocationManager.locationServicesEnabled() ) {
            if ( CLLocationManager.headingAvailable() ) {
                newMode = .followWithHeading
            }
            else {
                newMode = .follow
            }
        }

        if (mode != newMode)
        {
            DispatchQueue.main.async {
                mapView.setUserTrackingMode(newMode, animated: true)
            }
        }
}