Regarding Apple's KMLViewer placemarkDescription and annotation subtitle

前端 未结 1 943
终归单人心
终归单人心 2021-01-24 10:01

In my app I am using Apple\'s KMLViewer to show annotations that I get from a KML file.In the file KMLParser.m, there is an instance variable, placemarkDescription

相关标签:
1条回答
  • 2021-01-24 10:38

    It's not clear how much of the KMLViewer sample app code you're using but one way to do this is to create your own annotation class instead of using the MKPointAnnotation class like the sample app does.

    The custom class (eg. "PlacemarkAnnotation"), should implement the MKAnnotation protocol or be a sub-class of MKShape (if you are using the KMLViewer code). In the custom class, add a placemarkDescription property.

    Where the KMLViewer code currently creates an MKPointAnnotation object, create a PlacemarkAnnotation instead and set its placemarkDescription property instead of the subtitle property.

    Then in the viewForAnnotation delegate method, set the rightCalloutAccessoryView to a detail disclosure button.

    Next, add to the project a detail view controller with a UIWebView in it. Add a placemarkDescription property to the view controller. In the viewDidLoad method, call loadHTMLString on the web view and pass it placemarkDescription (I think you can pass nil for the baseURL).

    In the map view's calloutAccessoryControlTapped delegate method, create the detail view controller, set its placemarkDescription property and present it:

    -(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view 
        calloutAccessoryControlTapped:(UIControl *)control
    {
        DetailViewController *dvc = [[DetailViewController alloc] init...
        PlacemarkAnnotation *pa = (PlacemarkAnnotation *)view.annotation;
        dvc.placemarkDescription = pa.placemarkDescription;
        [self presentModalViewController:dvc animated:YES];
        [dvc release];
    }
    


    Edit:

    First, it looks like it will be best to subclass MKShape for your custom class instead of implementing the MKAnnotation protocol. The rest of the KMLViewer code is based on this assumption. So change @interface PlacemarkAnnotation2 : NSObject <MKAnnotation> to @interface PlacemarkAnnotation2 : MKShape. (By the way, for the NSString properties, copy is more appropriate than retain and it'll get rid of warnings.)

    It also looks like you may have changed the type of the mkShape ivar in KMLPlacemark (and other places) from MKShape to something else. Change these types back to MKShape.

    Next, _createShape might not be the best place to set the placemarkDescription since that method is called for both overlays and annotations. Remove your changes from that method and put them in the point method (also in KMLPlacemark). Note there are a couple of potential memory-related issues with your changes. Here's my suggestion:

    - (void)_createShape
    {
        if (!mkShape) {
            mkShape = [[geometry mapkitShape] retain];
            mkShape.title = name;
            // Skip setting the subtitle for now because they're frequently
            // too verbose for viewing on in a callout in most kml files.
        }
    }
    
    - (id <MKAnnotation>)point
    {
        [self _createShape];
    
        if ([mkShape isKindOfClass:[PlacemarkAnnotation2 class]])
        {
            if (placemarkDescription != nil)
                //check for nil, otherwise will crash when 
                //passing to stringByAppendingString below
            {
                NSString *lessThan = @"&lt;";
                NSString *greaterThan = @"&gt;";
    
                placemarkDescription = [placemarkDescription stringByReplacingOccurrencesOfString:lessThan
                                                                                       withString:@"<"];
                placemarkDescription = [placemarkDescription stringByReplacingOccurrencesOfString:greaterThan
                                                                                       withString:@">"];
                NSString *beforeBody = @"<html><body>";
                NSString *afterBody = @"</body></html>";
    
                NSString *finalContent = [[beforeBody stringByAppendingString:placemarkDescription] 
                                          stringByAppendingString:afterBody];
    
                placemarkDescription = [finalContent retain];
                    //added retain above since finalContent is autoreleased
                    //and we are setting the ivar manually.  otherwise,
                    //can result in EXC_BAD_ACCESS later.
            }
    
            PlacemarkAnnotation2 *pa2 = (PlacemarkAnnotation2 *)mkShape;
            pa2.placemarkDescription = placemarkDescription;
    
            return (id <MKAnnotation>)mkShape;
        }
    
        return nil;
    }
    
    0 讨论(0)
提交回复
热议问题