2013-05-17 72 views
3

我有MKUserTrackingModeFollowWithHeading的MKMapView。 但是很多事情改變了userTrackingMode到MKUserTrackingModeFollow或無, 所以我實現了,放大時使用MKMapView在setUserTrackingMode上崩潰

- (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]; 
    } 
} 

一切都很好,但每次我在地圖最詳細級別縮放,該應用會EXC_BAD_ACCESS在該行setUserTrackingMode:以上MKUserTrackingModeFollowWithHeading所示。

我該怎麼做才能避免崩潰?如果可能,我不想使用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

+0

我覺得這個崩潰(MKUserTrackingModeFollowWithHeading崩潰)是一種對SO的流行,你應該看看比其他SO張貼關於這個崩潰 – danypata

+0

我一直在尋找的SO,但我找不到......謝謝。 – kinamin

+0

而不是強制重置跟蹤模式,你不能只將'scrollEnabled'設置爲'NO'?這樣用戶可以縮放,但不能滾動,因此用戶跟蹤模式不應該因用戶交互而改變,如果它?另外,如果這不是您目前使用的模式,您是不是應該只設置跟蹤模式?如果'didChangeUserTrackingMode'將其設置爲您想要的模式,則不需要再次設置用戶跟蹤模式。 – Rob

回答

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(這應該防止用戶偶然啓動跟蹤模式的改變)。

+0

這完美解決了問題!我一起使用這個和'scrollEnabled = NO'。我永遠不會永遠感謝你! – kinamin

+0

@kinamin僅供參考,我注意到,當你完全放大時,它會將跟蹤模式設置爲「MKUserTrackingModeFollow」,即使您只是將其設置爲「MKUserTrackingModeFollowWithHeading」,並且最終會產生一個「didChangeUserTrackingMode」調用循環,有時會導致崩潰。我在'regionWillChangeAnimated'和'regionDidChangeAnimated'中設置了一個標誌,並且似乎解決了這個問題,但它仍然不太正確。底線,如果你有問題,讓我知道,我可能會有更多的建議。 – Rob

+0

您的意思是trackingMode在'regionWillChangeAnimated'或'regionDidChangeAnimated'方法中檢測到縮放時還必須更改爲MKUserTrackingModeFollowWithHeading?或僅在'regionWillChangeAnimated' /'regionDidChangeAnimated'中,但不在'didChangeUserTrackingMode'中?當然,縮放時它似乎很慢。也許'didChangeUserTrackingMode'循環發生我認爲。 – kinamin

-1

斯威夫特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) 
      } 
     } 
} 
相關問題