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.
- Check if ‘tap’ IBAction is binded with some cocoa control element (say UIbutton touchUpInside event)
- Check if ‘tap’ IBAction has been declared in Class
- You may be using
action:@selector(tap:)
instead ofaction:@selector(tap)
Handle
didFailWithError
delegate of Location Manager to get more detail about error
Syntax:(void) locationManager: (CLLocationManager *)manager didFailWithError: (NSError *) error
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
How to Add Navigation Interface After Create a Tab Bar Controller Programmatically (Swift)
Set the Status Bar to Black Colour
Initializing Swift Properties That Require "Self" as an Argument
Uiapplicationlaunchoptionsremotenotificationkey Not Getting Userinfo
Storing [Nsnull Null] Values in Nsuserdefaults, from JSON Serialization, Causes Unwanted Exceptions
How to Determine File Size on Disk of a Video Phasset in iOS8
iOS - Using Uisearchdisplaycontroller with Uisearchbar That Is Uibarbuttonitem in Uitoolbar
How to Disable Qlpreviewcontroller Print Button
How to Get Index(Of:) to Return Multiple Indices
iOS Fix Search Bar on Top of the Uitableviewcontroller
How to Create Scrollable Table in Skspritekit
Using Wcsession with More Than One Viewcontroller
Add Custom Cordova Plugin to Ibm Worklight 6.1
Ciimage Display Mtkview VS Glkview Performance
iPad 3 - Opengl Bug with Keagldrawablepropertyretainedbacking and Retina