Warning in Custom Map Annotations iPhone
Latitude and Longitude have differing bounds:
- (-90, 90) for Lat
- (-180, 180) for Long
Passing a value outside of those bounds will cause the custom class to be deallocated and therefore giving you the error that you're receiving. Make sure that you are passing the correct values for both Latitude and Longitude.
It would be really nice if Apple passed a bounding error for this instead of an early release error. That would've saved me roughly 5 hours worth of time
Error in displaying annotations in map
Because of empty text, it might be converted to 0.000,0.000 or so, better approach is to check [latitude_value.text isEqualToString:@""]
and if not then continue with your task. Let me know if this helps.
I guess if this fails, you can just remove all annotations from the map.
Custom title for map annotation
If you want to set a different title and subtitle for each point you'll need to provide a text box for the user to enter the data. Once done it's as simple as the code you already have
NSString *title = [self.titleField stringValue];
[annotation setTitle:@"title"];
NSString *subtitle = [self.subtitleField stringValue];
[annotation setSubtitle:@"title"];
However you may not have the screen space to show three textfields. What I do is create the pin with a default name, then allow the user to open the callout bubble, or open it automatically and show a button to edit it, then show a modal dialog over the top to edit the title and subtitle
If you saved every coordinate.latitude
under the key allPins_latitude
then each one would overwrite the previous and you'd only have the last one saved. If your pins are all stored as an array, store the array.
iOS Swift MapKit Custom Annotation
I recommend subclassing `MKPointAnnotation.
Pokémon Pin
I have included only the necessary code to display a custom map pin. Think of it as a template.
Outline
We will create a point annotation object and assigning a custom image name with the
CustomPointAnnotation
class.We will subclass the
MKPointAnnotation
to set image and assign it on the delegate protocol methodviewForAnnotation
.We will add an annotation view to the map after setting the coordinate of the point annotation with a title and a subtitle.
We will implement the
viewForAnnotation
method which is anMKMapViewDelegate
protocol method which gets called for pins to display on the map.viewForAnnotation
protocol method is the best place to customise the pin view and assign a custom image to it.We will dequeue and return a reusable annotation for the given identifier and cast the annotation to our custom
CustomPointAnnotation
class in order to access the image name of the pin.We will create a new image set in
Assets.xcassets
and place image@3x.png and image@2x.png accordingly.Don't forget plist.
NSLocationAlwaysUsageDescription
and NSLocationWhenInUseUsageDescription
As always test on a real device.
The swizzle /p>
//1
CustomPointAnnotation.swift
import UIKit
import MapKit
class CustomPointAnnotation: MKPointAnnotation {
var pinCustomImageName:String!
}
//2
ViewController.swift
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
@IBOutlet weak var pokemonMap: MKMapView!
let locationManager = CLLocationManager()
var pointAnnotation:CustomPointAnnotation!
var pinAnnotationView:MKPinAnnotationView!
override func viewDidLoad() {
super.viewDidLoad()
//Mark: - Authorization
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
pokemonMap.delegate = self
pokemonMap.mapType = MKMapType.Standard
pokemonMap.showsUserLocation = true
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = CLLocationCoordinate2D(latitude: 35.689949, longitude: 139.697576)
let center = location
let region = MKCoordinateRegionMake(center, MKCoordinateSpan(latitudeDelta: 0.025, longitudeDelta: 0.025))
pokemonMap.setRegion(region, animated: true)
pointAnnotation = CustomPointAnnotation()
pointAnnotation.pinCustomImageName = "Pokemon Pin"
pointAnnotation.coordinate = location
pointAnnotation.title = "POKéSTOP"
pointAnnotation.subtitle = "Pick up some Poké Balls"
pinAnnotationView = MKPinAnnotationView(annotation: pointAnnotation, reuseIdentifier: "pin")
pokemonMap.addAnnotation(pinAnnotationView.annotation!)
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print(error.localizedDescription)
}
//MARK: - Custom Annotation
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
let reuseIdentifier = "pin"
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseIdentifier)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
annotationView?.canShowCallout = true
} else {
annotationView?.annotation = annotation
}
let customPointAnnotation = annotation as! CustomPointAnnotation
annotationView?.image = UIImage(named: customPointAnnotation.pinCustomImageName)
return annotationView
}
}
iphone mkannotation: warning on left callout after map has loaded
If you end up re-using an annotation view, myImageView isn't created, yet you're releasing it. Set myImageView to nil at the top.
- (MKAnnotationView *) mapView:(MKMapView *)thisMapView viewForAnnotation:(MapAnnotations *)annotation {
static NSString *MapIdentifier = @"MapIdentifier";
UIImageView *myImageView = nil;
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[thisMapView dequeueReusableAnnotationViewWithIdentifier:MapIdentifier];
if(annotationView == nil) {
NSString * id = [NSString stringWithFormat:@"%d", (annotation).tag];
NSString * postPhoto = [NSString stringWithFormat:@"id=%@",id];
NSString * hostStrPhoto = @"http://domain.com/get_image.php?";
hostStrPhoto = [hostStrPhoto stringByAppendingString:postPhoto];
NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:hostStrPhoto]];
myImageView = [[UIImageView alloc] initWithImage:[UIImage imageWithData: imgData]];
myImageView.frame = CGRectMake(0,0,31,31);
annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:MapIdentifier] autorelease];
}
annotationView.animatesDrop=TRUE;
annotationView.canShowCallout = YES;
annotationView.leftCalloutAccessoryView = myImageView; //<--where I am getting the error, after all the annotations have loaded.
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
return annotationView;
[myImageView release];
}
Custom Annotation pin interfere with mkmapview's showuserlocation on Iphone
Try this
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
// if it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
if ([[annotation title] isEqualToString:@"Destination"])
{
MKPinAnnotationView *newAnnotation = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"greenpin"];
newAnnotation.pinColor = MKPinAnnotationColorGreen;
newAnnotation.animatesDrop = YES;
newAnnotation.canShowCallout = YES;
return newAnnotation;
}
}
Obj-C - All Custom MKMapView annotations not always showing on MapView?
You should check if some of your geocoding requests are failing inconsistently.CLGeocoder
rate limits your requests and if you do too many requests in a short time, you'll receive an error. https://developer.apple.com/documentation/corelocation/clgeocoder/1423509-geocodeaddressstring?language=objc
Check if you are getting any reason for failure inside NSError* error
inside the completionHandler block.
As many times as it fails, you should see as many less number of annotations on the MapView because it is not entering the following code path.
if (placemarks && placemarks.count > 0) {
// Not entering here
}
if (nil != error) {
// Could land here
}
The only other reason would be not properly calculating map region to show all annotations in screen. Make sure you are calculating/adjusting the region correctly upon each annotation being added to the mapView.
// Define these variables globally in the view controller
CLLocationDegrees minLatitude = 90.0;
CLLocationDegrees maxLatitude = -90.0;
CLLocationDegrees minLongitude = 180.0;
CLLocationDegrees maxLongitude = -180.0;
// Call following method every time a new annotation needs to be added to the mapView
-(void)addAnnotation:(id<MKAnnotation>)annotation toMapView:(MKMapView*)mapView {
// Add the annotation to map
[mapView addAnnotation:annotation];
// Set the map region to make it visible along with all other annotations
CLLocationDegrees latitude = annotation.coordinate.latitude;
CLLocationDegrees longitude = annotation.coordinate.longitude;
minLatitude = min(minLatitude, latitude);
maxLatitude = max(maxLatitude, latitude);
minLongitude = min(minLongitude, longitude);
maxLongitude = max(maxLongitude, longitude);
CLLocationDegrees latitudeDelta = (maxLatitude - minLatitude);
CLLocationDegrees longitudeDelta = (maxLongitude - minLongitude);
CLLocationDegrees midLatitude = (maxLatitude - latitudeDelta/2);
CLLocationDegrees midLongitude = (maxLongitude - longitudeDelta/2);
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(midLatitude, midLongitude);
MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
MKCoordinateRegion region = MKCoordinateRegionMake(center, span);
if (CLLocationCoordinate2DIsValid(center)) {
[mapView setRegion:region animated:YES];
}
}
Why does a custom MKMapView annotation image disappear on touch?
Answering my own question here, just in case others have the same issue. Notice that I am using "MKPinAnnotationView" - it should be changed to "MKAnnotationView" and everything works.
Fixed code:
- (MKAnnotationView *)mapView:(MKMapView *)newMapView viewForAnnotation:(id )newAnnotation {
MKAnnotationView *annotation = [[MKAnnotationView alloc] initWithAnnotation:newAnnotation reuseIdentifier:@"currentloc"];
if (annotation == nil) {
annotation = [[MKAnnotationView alloc] initWithAnnotation:newAnnotation reuseIdentifier:@"currentloc"];
}
annotation.image = [UIImage imageNamed:@"anno.png"];
annotation.canShowCallout = YES;
annotation.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"bus_stop_30x30.png"]];
annotation.leftCalloutAccessoryView = imgView;
return annotation;
}
Related Topics
Uicontrolstate.Normal Is Unavailable
What Does It Mean for Something to Be Thread Safe in iOS
Why Does "Try Catch" in Objective-C Cause Memory Leak
Why Isn't Preferredcontentsize Used by iPhone 6 Plus Landscape
iOS How to Dismiss Uialertview with One Tap Anywhere
Xcode 10 Not Being Able to Archive Project
Will Fork() in iOS App Likely Be Rejected by Apple's Vetting Process
Swift Execute Asynchronous Tasks in Order
React-Native Loading Image Over Https Works While Http Does Not Work
Warning in Custom Map Annotations Iphone
Make Swift Assume Degrees for Trigonometry Calculations
Pdfkitten Is Highlighting on Wrong Position
Draggesture on a VStack with Lot of Buttons, How to Detect When the Drag Is Inside a Button
Uiscrollview with Dynamically Sized Content
How to Control My Headset for My Music Player
iOS Swift 3:Convert "Yyyy-Mm-Dd'T'Hh:Mm:Ssz" Format String to Date Object