Unrecognized Error in Mapview (Ios)

Unrecognized Error in MapView (iOS)

Can't tell where the invalid coordinates are coming from but I suggest adding the following checks to the zoomToUserLocation method.

Just checking if userlocation is nil is not enough. You have to also check if the location property inside userlocation is nil or not. Then, you can use the coordinate property (especially when you're using the coordinates outside the didUpdateUserLocation delegate method).

Also, just checking if coordinate is 0,0 (technically a valid coordinate) is not recommended as the struct will be "zero" if it's never been set or it could even be filled with random data. The Core Location framework's CLLocationCoordinate2DIsValid function is used as the last line of defense to prevent an invalid region.

You could also check the timestamp and horizontalAccuracy if you want.

- (void)zoomToUserLocation:(MKUserLocation *)userlocation
{
if (!userlocation)
return;

if (!userlocation.location)
{
NSLog(@"actual location has not been obtained yet");
return;
}

//optional: check age and/or horizontalAccuracy
//(technically should check if location.timestamp is nil first)
NSTimeInterval locationAgeInSeconds =
[[NSDate date] timeIntervalSinceDate:userlocation.location.timestamp];
if (locationAgeInSeconds > 300) //adjust max age as needed
{
NSLog(@"location data is too old");
return;
}

if (!CLLocationCoordinate2DIsValid(userlocation.coordinate))
{
NSLog(@"userlocation coordinate is invalid");
return;
}

MKCoordinateRegion region;
region.center = userlocation.coordinate;
region.span = MKCoordinateSpanMake(2.0, 2.0);

//region = [self.mapView regionThatFits:region];
//don't need to call regionThatFits explicitly, setRegion will do it

[self.mapView setRegion:region animated:YES];
}

Additionally (possibly unrelated and you may have already done this but), based on a couple of your previous questions related to this, you might want to clear and re-set the map view's delegate in the map view controller's viewWillDisappear and viewWillAppear methods to prevent certain errors:

-(void)viewWillAppear:(BOOL)animated
{
mapView.delegate = self;
}

-(void)viewWillDisappear:(BOOL)animated
{
mapView.delegate = nil;
}

unrecognized selector sent to instance in MapView iof OS

Perform following reviews in your code.

  1. Check if ‘tap’ IBAction is binded with some cocoa control element (say UIbutton touchUpInside event)
  2. Check if ‘tap’ IBAction has been declared in Class
  3. You may be using action:@selector(tap:) instead of action:@selector(tap)
  4. Handle didFailWithError delegate of Location Manager to get more detail about error
    Syntax:

    (void) locationManager: (CLLocationManager *)manager
 didFailWithError: (NSError *) error

  5. Check of Segue with ID ‘Map’ does exists

Crash with unrecognized selector when user touches annotation

_calloutAnnotation does not contain annotation view. I think that you have somewhere code like this @prorerty (weak, nonatomic) MKAnnotation * calloutAnnotation; changing weak to strong should help.

MKMarkerAnnotationView Error, Terminating app due to uncaught exception

You say it’s reporting:

Error [XXX.CustomPinAnnotation memberAnnotations]: unrecognized selector sent to instance 0x2835e16c0

The memberAnnotations is a MKClusterAnnotation method. But it’s trying to call that method on your CustomPinAnnotation object. Somewhere, it’s trying to use a CustomPinAnnotation in a context where it was expecting a MKClusterAnnotation.

I’ve had troubles manifesting your problem, and I’m not sure you’ve shared enough for us to reproduce it. But I can easily see how it get be confused. There are three annotation types, not only MKUserLocation and CustomPinAnnotation, but also MKClusterAnnotation. Your mapView(_:viewFor:) only contemplates the existence of the first two types. You can make it handle MKClusterAnnotation, too, if you want:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
} else if annotation is MKClusterAnnotation {
return mapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultClusterAnnotationViewReuseIdentifier, for: annotation)
}

let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier, for: annotation)

guard
let markerAnnotationView = annotationView as? MKMarkerAnnotationView,
let annotation = annotation as? CustomPinAnnotation
else {
return annotationView
}

markerAnnotationView.clusteringIdentifier = annotation.clusteringIdentifier
markerAnnotationView.displayPriority = .required
// markerAnnotationView.glyphText = annotation.glyphText
markerAnnotationView.glyphImage = annotation.glyphImage
markerAnnotationView.glyphTintColor = annotation.glyphTintColor
markerAnnotationView.markerTintColor = annotation.markerTintColor
return markerAnnotationView
}

Personally, though, I'd suggest removing mapView(_:viewFor:) entirely, and instead define your own annotation view class that does this configuration:

class CustomAnnotationView: MKMarkerAnnotationView {
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
update(for: annotation)
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override var annotation: MKAnnotation? { didSet { update(for: annotation) } }

func update(for annotation: MKAnnotation?) {
displayPriority = .required

guard let annotation = annotation as? CustomPinAnnotation else { return }

clusteringIdentifier = annotation.clusteringIdentifier
// markerAnnotationView.glyphText = annotation.glyphText
glyphImage = annotation.glyphImage
glyphTintColor = annotation.glyphTintColor
markerTintColor = annotation.markerTintColor
}
}

And, of course, make sure to register it (and your cluster annotation view, too):

mapView.register(CustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)
mapView.register(MKMarkerAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultClusterAnnotationViewReuseIdentifier)

But the key is that the default implementation of mapView(_:viewFor:) handles all three types of annotation views automatically. And this way, we take gritty “how do I render this annotation view” code out of the view controller (or whatever the MKMapViewDelegate was) and into the annotation view class, where it belongs.

How to identify the unrecognized selector and the object that doesn't recognize it?

This line:

[self.mapView removeAnnotation: self.mapView.annotations];

should probably be:

[self.mapView removeAnnotations: self.mapView.annotations];

removeAnnotation: expects a single annotation. removeAnnotations: expects an array of annotations.

This will solve both of your issues.

FYI - never ignore compiler warnings. If your code isn't compiling clean it will likely crash.

Mapkit addAnnotation exception: unrecognized selector sent to instance

Your CityAnnotation class has to provide a property/method named coordinate. See the MKAnnotation Protocol Reference for details.

You may be able to fix your problem by just renaming your coords property to coordinate.

MapView error on iOS

You need to declare that your class implements the MKMapViewDelegate methods. In your ViewController.h header file, change the line

@interface ViewController : UIViewController {

to

@interface ViewController : UIViewController <MKMapViewDelegate> {


Related Topics



Leave a reply



Submit