We are trying to create a mapview with annotations loaded from a xml file. This works so far, and is making use of the KMLViewer code on the apple developer library. Now we are trying to load the data from the XML file into the detailview but only the corresponding entry. So when you click on details on a city for instance, details must be loaded from the xml file of that city.
We are trying for days now but just don't know where to start. We have the following code now:
detailviewcontroller.m
#import "DetailViewController.h"
@implementation DetailViewController
@synthesize address;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib
- (void)viewDidLoad
{
TabbedCalculationAppDelegate *appDelegate = (TabbedCalculationAppDelegate *)[[UIApplication sharedApplication] delegate];
address.text = appDelegate.addressInput1 ;
[super viewDidLoad];
}
- (void)viewDidUnload
{
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc
{
[super dealloc];
}
Map view
#import "locator.h"
#import "DetailViewController.h"
@implementation locator
@synthesize map, detailViewController, rightButton, customPinView;
- (void)viewDidLoad
{
[super viewDidLoad];
// create a custom navigation bar button and set it to always says "Back"
UIBarButtonItem *temporaryBarButtonItem = [[UIBarButtonItem alloc] init];
temporaryBarButtonItem.title = @"Back";
self.navigationItem.backBarButtonItem = temporaryBarButtonItem;
[temporaryBarButtonItem release];
// Locate the path to the route.kml file in the application's bundle
// and parse it with the KMLParser.
NSString *path = [[NSBundle mainBundle] pathForResource:@"branches" ofType:@"kml"];
kml = [[KMLParser parseKMLAtPath:path] retain];
// Add all of the MKOverlay objects parsed from the KML file to the map.
NSArray *overlays = [kml overlays];
[map addOverlays:overlays];
// Add all of the MKAnnotation objects parsed from the KML file to the map.
NSArray *annotations = [kml points];
[map addAnnotations:annotations];
// Walk the list of overlays and annotations and create a MKMapRect that
// bounds all of them and store it into flyTo.
MKMapRect flyTo = MKMapRectNull;
for (id <MKOverlay> overlay in overlays) {
if (MKMapRectIsNull(flyTo)) {
flyTo = [overlay boundingMapRect];
} else {
flyTo = MKMapRectUnion(flyTo, [overlay boundingMapRect]);
}
}
for (id <MKAnnotation> annotation in annotations) {
MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0);
if (MKMapRectIsNull(flyTo)) {
flyTo = pointRect;
} else {
flyTo = MKMapRectUnion(flyTo, pointRect);
}
}
// Position the map so that all overlays and annotations are visible on screen.
MKCoordinateRegion mapRegion;
mapRegion.center.latitude = 51.522416;
mapRegion.center.longitude = 5.141602;
mapRegion.span.latitudeDelta = 5;
mapRegion.span.longitudeDelta = 5;
[map setRegion:mapRegion animated:YES];
}
#pragma mark MKMapViewDelegate
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
return [kml viewForOverlay:overlay];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
// if it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
// handle custom annotations
// // try to dequeue an existing pin view first
static NSString* BridgeAnnotationIdentifier = @"bridgeAnnotationIdentifier";
MKPinAnnotationView* pinView = (MKPinAnnotationView *)
[map dequeueReusableAnnotationViewWithIdentifier:BridgeAnnotationIdentifier];
if (!pinView)
{
// if an existing pin view was not available, create one
customPinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:BridgeAnnotationIdentifier] autorelease];
customPinView.pinColor = MKPinAnnotationColorPurple;
customPinView.animatesDrop = YES;
customPinView.canShowCallout = YES;
// add a detail disclosure button to the callout which will open a new view controller page
//
// note: you can assign a specific call out accessory view, or as MKMapViewDelegate you can implement:
// - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control;
//
rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
customPinView.rightCalloutAccessoryView = rightButton;
return customPinView;
}else{
return pinView;}
return nil;
}
#pragma mark -
#pragma mark MKMapViewDelegate
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
{
if (view.annotation == mapView.userLocation)
return;
rightButton = (DetailViewController *)view.annotation;
//show detail view using buttonDetail...
}
// the detail view does not want a toolbar so hide it
[self.navigationController setToolbarHidden:YES animated:YES];
[开发者_如何学运维self.navigationController pushViewController:self.detailViewController animated:YES];
}
- (void)viewDidUnload
{
self.detailViewController = nil;
}
- (void)dealloc
{
[detailViewController release];
[super dealloc];
}
@end
As you can see the code is starting to look messy after trying tons of stuff, but we don't really know where to start.
Any help would be extremely appreciated
Thnx in advance!
Please have a look at the interface of the KMLPlacemark in KMLParser, there you can see what is exactly parsed and stored of an xml placemark element. For example the address is missing. So you will have to add all the information you want the parser to gather by implementing the fields in the KMLPlacemark class and alter the KMLParser methods:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName ...
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName ...
as well as some parts of the KMLPlacemark implementation. To fill the new fields with the parser you'll have to write methods like the - (void)beginName
and - (void)endName
. It will get a bit tricky when the elements you want to parse have children.
It could be helpful to split the KMLParser file into several files which contain one class each.
If you have achieved that and your placemark contains all the needed details you can catch the tap on an annotation with the MKMapViewDelegate protocol. Implement didDeselectAnnotationView, which could look like this:
- (void) mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
// implementation example of placemarkForAnnotation below
KMLPlacemark * placemark = [kml placemarkForAnnotation:view.annotation];
MyDetailViewController * myDetailViewController = [[MyDetailViewController alloc] initWithPlacemark:placemark];
[self presentModalViewController:myDetailViewController animated:YES];
[myDetailViewController release];
}
In KMLParser add
- (KMLPlacemark *)placemarkForAnnotation:(id <MKAnnotation>)point
{
// Find the KMLPlacemark object that owns this point and return it
for (KMLPlacemark *placemark in _placemarks) {
if ([placemark point] == point)
return placemark;
}
return nil;
}
Hope I could point you in the right direction. It'll be some work ;)
精彩评论