Note that there are some explanatory texts on larger screens.

plurals
  1. POWeird behaviour in MKMapView - pins disappearing
    text
    copied!<p>Within my app we have a screen with an MKMapView.</p> <p>This map shows pins for a bunch of Locations (location is a model defined within the app).</p> <p>When running in the simulator this works fine. However, when running this on a device the pins seem to disappear and re-appear almost each time the map is panned. Even slight touches and movements can cause the map to show and hide pins. </p> <p>The map isn't particularly busy, even when showing one pin it will show and hide it.</p> <p>Has anybody any idea why this might be happening? I've pasted my code below... It's a Rubymotion app so the code is in Ruby.</p> <h2>- UPDATE -</h2> <p>I've added the Objective C equivalent to this Ruby code below. Apologies if there are a couple of typos or idiomatic errors, it's been a while since I've written any OC.</p> <h2>- UPDATE 2 -</h2> <p>Watching the logger, I can see that <code>mapView:viewForAnnotation</code> is being called each time a map pin disappears/reappears.</p> <p>Also each time <code>mapView:regionDidChangeAnimated</code> I can see that the Object IDs for the annotations are the same - so I don't think they're being removed (which they shouldn't be)</p> <pre><code># ==================== # = 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 &gt; 0 and meters &lt; 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 &amp;&amp; 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 </code></pre> <h2>Objective C</h2> <pre><code>#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 &gt; 0 &amp;&amp; meters &lt; 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 &amp;&amp; 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 &amp;&amp; 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 &lt; MKAnnotation &gt;)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) } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload