viewForOverlay method not being called while parsing KML - ios

I'm using KML to show some overlays in map view. After parsing KML file I added overlay to my map view, but the map view delegate method viewForOverlay is not being called even if I set delegate property to map view.
What are the possible reasons for this problem?
NSURL *url = [NSURL fileURLWithPath:filePath];
kmlParser = [[KMLParser alloc] initWithURL:url];
[kmlParser parseKML];
// Add all of the MKOverlay objects parsed from the KML file to the map.
NSArray *overlays = [kmlParser overlays];
[self.mapView addOverlays:overlays];
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
return [kmlParser viewForOverlay:overlay];
}
I have done it using KMLViewer example.

Related

How to get map annotation title in this method

i want to get annotation title & subtitle from this method.
what the way go get that.
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{
//NSString * title = [annotations title];
}
The view has an annotation property that you can use which will return the annotation you originally used when creating the view.

MKPinAnnotationView pinColor

I can't figure out why a MKPinAnnotationView associated (in theory) with a MKPointAnnotation doesn't appear on the map. In fact, the pin appears but it isn't purple as it should be...
Here is the code:
MKPointAnnotation *myPersonalAnnotation= [[MKPointAnnotation alloc]init];
myPersonalAnnotation.title= [appDelegate.theDictionary objectForKey:#"theKey"];
myPersonalAnnotation.coordinate=CLLocationCoordinate2DMake(6.14, 10.7);
MKPinAnnotationView *myPersonalView=[[MKPinAnnotationView alloc] initWithAnnotation:myPersonalAnnotation reuseIdentifier:#"hello"];
myPersonalView.pinColor=MKPinAnnotationColorPurple;
[myMap addAnnotation:myPersonalAnnotation];
If you want to create an annotation view different from the default red pin, you have to create and return it in the map view's viewForAnnotation delegate method.
The map will automatically call the viewForAnnotation delegate method whenever it needs to show some annotation (either the built-in user location or annotations you add).
Remove the local creation of myPersonalView from before the call to addAnnotation and implement the viewForAnnotation method instead.
For example:
//in your current method...
MKPointAnnotation *myPersonalAnnotation= [[MKPointAnnotation alloc]init];
myPersonalAnnotation.title= [appDelegate.theDictionary objectForKey:#"theKey"];
myPersonalAnnotation.coordinate=CLLocationCoordinate2DMake(6.14, 10.7);
[myMap addAnnotation:myPersonalAnnotation];
//...
//add the viewForAnnotation delegate method...
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
//if annotation is the user location, return nil to get default blue-dot...
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
//create purple pin view for all other annotations...
static NSString *reuseId = #"hello";
MKPinAnnotationView *myPersonalView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseId];
if (myPersonalView == nil)
{
myPersonalView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId];
myPersonalView.pinColor = MKPinAnnotationColorPurple;
myPersonalView.canShowCallout = YES;
}
else
{
//if re-using view from another annotation, point view to current annotation...
myPersonalView.annotation = annotation;
}
return myPersonalView;
}
Make sure the map view's delegate property is set otherwise the delegate method won't get called.
In code, use myMap.delegate = self; (eg. in viewDidLoad) or make the connection in Interface Builder if myMap is an IBOutlet.

Properties of custom Annotation don't visible in delegate methods

I have many custom annotations to whom I gave the property (NameTable and ID). I set this property before AddAnnotation the moment of creation, but these property in the delegate methods are no longer visible. I have multiple annotation associated with elements of tables taken from a database. How can I make them visible in the delegate methods?
- (void)viewDidLoad
{
//......
for(int i=0; i<6; i++){ //loop for create multiple annotations
AnnotationCustom *annotationIcone =[[AnnotationCustom alloc]initWithCoordinates:coord
title:self.myTable.title subTitle:self.myTable.address];
annotationIcone.nameTable = [NSString stringWithFormat:#"%#", self.myTableName];
annotationIcone.ID = i+1;
[self.mapView addAnnotation: annotationIcone;
//.....
}
But in the delegate methods:
(MKAnnotationView *)mapView:(MKMapView *)mapview viewForAnnotation:(id
<MKAnnotation>)annotation
{
NSLog(#"The name of table is:#"%#", annotation.nameTable);
//property 'nameTable' not found on object of type '_strong id <MKAnnotation>
NSLog (#The name of table is:#%#", annotation.ID);
//property 'ID' not found on object of type '_strong id <MKAnnotation>
//......
}
In another method:
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{
NSLog(#"The name of table is %#", self.myTableName);
// here I get the name of last table open and not the name of table selected
}
In viewForAnnotation, you need to tell the compiler that the annotation is actually an AnnotationCustom object.
So you first need to do this:
AnnotationCustom *annotationCustom = (AnnotationCustom *)annotation;
and then try to access the nameTable property..
In the didSelectAnnotationView method, if what you want is to get the nameTable value of the annotation selected you need to do the following:
AnnotationCustom *annotationCustomSelected = (AnnotationCustom *)view.annotation;
NSLog(#"table name of annotation selected: %#", annotationCustomSelected.nameTable);

MKOverlays Combining Image Tiles And KML

I am trying to display tiled images with a kml overlay on top of the tiled images (code below) and am receiving the following error:
'NSInvalidArgumentException', reason: '-[MKPolyline tilesInMapRect:zoomScale:]: unrecognized selector sent to instance
Does anyone have any suggestions as to whether or not I am approaching the multiple overlays correctly or why I am getting this error?
Thanks in advance!
(void)viewDidLoad
{
[super viewDidLoad];
// Initialize the map overlay with tiles in the app's bundle.
NSString *tileDirectory = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"Tiles"];
MapOverlay *overlay1 = [[MapOverlay alloc] initWithDirectory:tileDirectory];
// Locate the path to the route.kml file in the application's bundle
// and parse it with the KMLParser.
NSString *path = [[NSBundle mainBundle] pathForResource:#"route" ofType:#"kml"];
NSURL *url = [NSURL fileURLWithPath:path];
kmlParser = [[KMLParser alloc] initWithURL:url];
[kmlParser parseKML];
// Add all of the MKOverlay objects parsed from the KML file to the map.
NSArray *overlay2 = [kmlParser overlays];
[map addOverlay:overlay1];
[map addOverlays:overlay2];
// Set the starting location.
CLLocationCoordinate2D startingLocation;
startingLocation.latitude = 0.00;
startingLocation.longitude =-0.00;
map.region = MKCoordinateRegionMakeWithDistance(startingLocation, 4600, 4600);
[map setCenterCoordinate:startingLocation];
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay1
{
MapOverlayView *view = [[MapOverlayView alloc] initWithOverlay:overlay1];
view.overlayAlpha = 1.0;
return view;
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay2:(id <MKOverlay>)overlay2
{
return [kmlParser viewForOverlay:overlay2];
}
#end
At least the viewForOverlay delegate method is not implemented correctly.
You've written two methods: mapView:viewForOverlay: and mapView:viewForOverlay2:.
But the map view will only always call mapView:viewForOverlay: since that is the method name defined by the MKMapViewDelegate protocol.
The mapView:viewForOverlay2: method will be ignored and not called by the map view.
So what happens is that when the overlay2 overlay array is added to the map, it calls the mapView:viewForOverlay: method which creates a MapOverlayView for the overlay (instead of getting the overlay view from kmlParser). This may cause issues (maybe MapOverlayView only handles MapOverlay-type overlays).
All overlays should be handled in the mapView:viewForOverlay: method.
To handle multiple types of overlays, check the overlay class and handle accordingly:
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
if ([overlay isKindOfClass:[MapOverlay class]])
{
MapOverlayView *view = [[MapOverlayView alloc] initWithOverlay:overlay];
view.overlayAlpha = 1.0;
return view;
}
//if not a MapOverlay, get from kmlParser...
return [kmlParser viewForOverlay:overlay];
}
Remove the mapView:viewForOverlay2: method.

Get URI from MKAnnotation selected on a MKmapview

This may be a design error instead of a syntax error, so let me know if I'm coding in the wrong direction here.
I'm new to Cocoa Touch/Objective-C and I've been working through tutorials on Core Data and MapKit. So far the app places an annotation on a mapview for items fetched from Core Data. I made a custom annotation object (called MapPin) that also holds a URI (NSURL*) pointing to the object in Core Data that it represents. When the user selects an annotation I want to use the URI property of that annotation to find which object in coredata the annotation represents.
This works if I add the annotation to the mapview beforehand. Here I add a MapPin annotation for each object "thing"
//viewWillAppear function in my ViewController
NSURL *uri = [[thing objectID] URIRepresentation];
MapPin *annotation = [[[MapPin alloc] initWithName:thing.common description:thing.latin coordinate:coordinate uri:uri] autorelease];
NSLog(#"MapPin URI: %#", [annotation.uri absoluteString]); //This works!
[_mapView addAnnotation:annotation];
NSLog(#"Placed Map Pin: %#", thing.common);
Later, after the user selects an annotation and clicks a button in the annotationView callout, I want to access the URI for the selected annotation
//the UIButton click action in my view controller
MSPTreesAppDelegate *del = (MSPTreesAppDelegate *)[UIApplication sharedApplication].delegate;
NSArray *annArray = _mapView.selectedAnnotations;
MapPin *selectedPin = [annArray objectAtIndex:0];
NSLog(#"Selected Pin Name: %#", selectedPin.name); //Works fine
NSLog(#"URI PASSED: %#", [selectedPin.uri absoluteString]); //Doesn't work
NSURL* uriForTree = selectedPin.uri; //also doesn't work
I notice in the debugger that before I add the annotation to the mapview, the URI property shows the correct string. After the (MapPin) annotation is selected from the map view, the URI property in the debugger just shows "invalid summary".
When I try to access the URI property the program ends and I get a "Thread 1: Program Received signal: "EXC_BAD_ACCESS"." error. The Log doesn't show anything helpful besides that.
I assume that my custom URI property for my MKAnnotation object isn't supported by the MKAnnotationView or the MKMapView, but I can't figure out where the URI is getting lost. Is there a way I can retrieve my URI property from the selected annotation? Other suggestions for methods to accomplish the same concept are welcome.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString *identifier = #"MapPin";
if ([annotation isKindOfClass:[MapPin class]]) {
NSLog(#"Annotation is a MapPin");
TreeAnnotationView *annotationView = (TreeAnnotationView *) [_mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[TreeAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
} else {
annotationView.annotation = annotation;
}
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
//Place details button in callout
UIButton * detailButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[detailButton setTitle:annotation.title forState:UIControlStateNormal];
[detailButton addTarget:self action:#selector(showDetails:) forControlEvents:UIControlEventTouchUpInside];
annotationView.rightCalloutAccessoryView = detailButton;
return annotationView;
}
return nil;
}
Why not make your MapPin be a subclass of NSManagedObject and have it implement MKAnnotation?
#interface MapPin : NSManagedObject <MKAnnotation>
#end
That way you one and only one model object to represent the pin and that model object is persisted through CoreData.
But your "EXC_BAD_ACCESS" and "invalid summary" indicate that the URI isn't' being retained (strong if you're using ARC).

Resources