MKMapView中的奇怪行为 - 引脚消失了

时间:2012-11-06 19:29:47

标签: objective-c ios mkmapview rubymotion

在我的应用程序中,我们有一个带有MKMapView的屏幕。

此地图显示了一堆地点的引脚(位置是应用中定义的模型)。

在模拟器中运行时,这很好用。但是,当在设备上运行时,引脚似乎消失并且几乎每次平移地图时都会重新出现。即使轻微的触摸和移动也可能导致地图显示和隐藏引脚。

地图不是特别繁忙,即使显示一个引脚也会显示并隐藏它。

有谁知道为什么会这样?我在下面粘贴了我的代码......这是一个Rubymotion应用程序,所以代码是Ruby。

- 更新 -

我在下面添加了与此Ruby代码等效的Objective C。抱歉,如果有一些拼写错误或惯用错误,那我已经写了一段时间了。

- 更新2 -

观察记录器,我可以看到每次地图引脚消失/重新出现时都会调用mapView:viewForAnnotation

每次mapView:regionDidChangeAnimated我都可以看到注释的对象ID是相同的 - 所以我认为它们不被删除(它们不应该被删除)

# ====================
# = MKMapKitDelegate =
# ====================

# Don't react if the user has moved less than three meters
USER_MOVE_THRESHOLD = 3

# The user location has changed
def mapView(mapView, didUpdateUserLocation: newLocation)
  NSLog("mapView:didUpdateUserLocation")
  return unless userLocation
  coord = newLocation.coordinate
  newLocationAsCL = CLLocation.alloc.initWithCoordinate(coord, altitude: 1, horizontalAccuracy:1, verticalAccuracy: -1, timestamp: nil)    
  meters = newLocationAsCL.distanceFromLocation(@lastUserCLLocation)

  # If user has moved less than 3m, return
  if meters > 0 and meters < USER_MOVE_THRESHOLD
    log "Distance was less than #{USER_MOVE_THRESHOLD} meters (#{meters}) - returning ***"
    return
  end

  # If the coord is the same as the previous user location
  if userLocation.coordinate.latitude == coord.latitude && userLocation.coordinate.longitude == coord.longitude
    log "User hasn't moved - returning ***"
  else
    log 'User has moved'
  end

  log "Did update user location: #{coord.latitude},#{coord.longitude}"

  if coord.latitude.to_f == 0.0 and coord.longitude.to_f == 0.0
    log 'Invalid coordinate received - returning ***'
  else
    fetchLocationsFromAPI
  end
end

def mapView(mapView, regionDidChangeAnimated: animated)
  NSLog("mapView:regionDidChangeAnimated:#{animated}")
  # do nothing here yet...
end

# create map pins...
def mapView(mapView, viewForAnnotation: annotation)
  log "mapView:viewForAnnotation: #{annotation.inspect}"

  if annotation.is_a?(Location)
    # If there's already an annotation we can use, use it! Otherwise create a new one
    annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(annotation.class.to_s) || begin
      annotationView = MKPinAnnotationView.alloc.initWithAnnotation(annotation, reuseIdentifier: annotation.class.to_s)
      annotationView.enabled        = true
      annotationView.canShowCallout = true
      annotationView.animatesDrop   = false
      annotationView.pinColor = MKPinAnnotationColorRed

      rightButton = UIButton.buttonWithType(UIButtonTypeDetailDisclosure)
      rightButton.addTarget(self, action: 'showLocationScreen:', forControlEvents: UIControlEventTouchUpInside)
      annotationView.rightCalloutAccessoryView = rightButton      
      annotationView      
    end
    annotationView.annotation = annotation
    annotationView.rightCalloutAccessoryView.tag = @mapLocations.index(annotation)
    return annotationView
  end
end

def mapView(mapViewm, didAddAnnotationViews: views)
  NSLog("mapView:didAddAnnotationViews - #{views}")
  # do nothing here yet...
end

目标C

#define kUserMoveThreshold 1

-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)newLocation
{
  NSLog(@"mapView:didUpdateUserLocation")
  if (!userLocation) {
    return;
  }
  CLLocationCoordinate2D coord = newLocation.coordinate;
  CLLocation newLocationAsCL = [[CLLocation alloc] initWithCoordinate: coord altitude: 1 horizontalAccuracy: 1 verticalAccuracy: -1 timestamp: NULL];
  CLLocationDistance meters = [newLocationAsCL distanceFromLocation: lastUserCLLocation];

  // If user has moved less than 3m, return
  if (meters > 0 && meters < kUserMoveThreshold){
    NSLog(@"Distance was less than %d meters (%d) - returning ***", kUserMoveThreshold, meters);
    return;
  }

  // If the coord is the same as the previous user location
  if (userLocation.coordinate.latitude == coord.latitude && userLocation.coordinate.longitude == coord.longitude){
    NSLog(@"User hasn't moved - returning ***");
    return;
  } else {
    NSLog(@"User has moved");  
  }
  NSLog(@"Did update user location: %f,%f", coord.latitude, coord.longitude);
  if (coord.latitude == 0.0 && coord.longitude == 0.0){
    NSLog(@"Invalid coordinate received - returning ***");
  } else {
    [self fetchLocationsFromAPI];
  }
}

-(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
  NSLog(@"mapView:regionDidChangeAnimated: %s", animated ? @"TRUE" : @"FALSE");
}

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id < MKAnnotation >)annotation
{
  NSLog(@"mapView:viewForAnnotation %s", annotation.description);

  if ([annotation isKindOfClass: [Location class]]){
      // If there's already an annotation we can use, use it! Otherwise create a new one
    MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier: [annotation className]];
    if (!annotationView){
      annotationView = [[MKPinAnnotationView alloc] initWithAnnotation: annotation reuseIdentifier: [annotation className]];
      [annotationView setEnabled: YES];
      [annotationView setCanShowCallout: YES];
      [annotationView setAnimatesDrop: NO];
      [annotationView setPinColor: MKPinAnnotationColorRed];

      UIButton *rightButton = [UIButton buttonWithType: UIButtonTypeDetailDisclosure];
      [rightButton addTarget: self action: @selector(showLocationScreen:) forControlEvents: UIControlEventTouchUpInside];
      [annotationView setRightCalloutAccessoryView: rightButton];
    }

    [annotationView annotation: annotation];
    [[annotationView rightCalloutAccessoryView] setTag: [mapLocations indexOfObject: annotation]];
    return annotationView
  }
}

-(void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views
{
  NSLog(@"mapView:didAddAnnotationViews %@", views)
}

2 个答案:

答案 0 :(得分:2)

这是Rubymotion的一个错误,似乎已经在1.30版本中解决了

= RubyMotion 1.30 =

...

  • 修正了MapKit注释引脚消失的错误,因为某些错误 Ruby对象(在本例中为MKAnnotations)将使用Bignum值作为 `hash'方法的返回值,在使用时无法正常工作 在MapKit中。

...

答案 1 :(得分:0)

创建引脚注释时,是否要将它们添加到mapView的注释数组中?

CLLocationCoordinate2D locationForSelectedFloorOffice;
locationForSelectedFloorOffice.longitude = [[myGeoCode objectAtIndex:0] floatValue] * 1.0;
locationForSelectedFloorOffice.latitude = [[myGeoCode objectAtIndex:1] floatValue] * 1.0;
MyLocation *annotation = [[MyLocation alloc] initWithName:dStore.selectedFloorRoomName address:@" " coordinate:locationForSelectedFloorOffice];
[self.mapView addAnnotation:annotation];