关于Apple的KMLViewer placemarkDescription和注释字幕

时间:2011-11-27 11:17:53

标签: iphone ios annotations mkmapview kml

在我的应用程序中,我使用Apple的KMLViewer来显示我从KML文件中获得的注释。在文件KMLParser.m中,有一个实例变量placemarkDescription,用于转换来自kml文件的Description标签下的信息to annotation subtitle.Now,在我的文件中,每个注释都以这种方式将信息存储在Description下:

<table width="280px"><tr><td></td><td></td></tr></table><table width="280px"><tr><td><b>Fitness Bulls</b>---Palester sportive. Sporti dhe koha e lire.....<a href="http://www.site.com/BIZ_DIR/810180432/Article-Fitness-Bulls.aspx" style="color:Green;" >Shikoni detajet >></a></td></tr><tr><td><a href="http://www.site.com/HartaV2/AddReview.aspx?gisDataId=8123855e-b798-40bc-ad2e-00346a931211" style="color:Green;" >Shkruani pershtypjen tuaj >> </a> <p style="float:right;">Postuar nga:<i>Import</i></p></td></tr></table>

在KMLParser.m中,我已将placemarkDescription从此转换为:

<html><body>

<table width="280px"><tr><td></td><td></td></tr></table><table width="280px"><tr><td>     
<b>Fitness Bulls</b>---Palester sportive. Sporti dhe koha e lire.....
<a href="http://www.site.com/BIZ_DIR/810180432/Article-Fitness-Bulls.aspx"     style="color:Green;" >Shikoni detajet >></a></td></tr><tr><td>
<a href="http://www.site.com/HartaV2/AddReview.aspx?gisDataId=8123855e-b798-40bc-ad2e-00346a931211" style="color:Green;" >Shkruani pershtypjen tuaj >> </a> <p 

 style="float:right;">Postuar nga:<i>Import</i></p></td></tr></table>

 </body></html>

我之所以这样做,是因为我希望将此字符串传递给webView并在其中可视化。 问题是,当kml加载时,方法获取描述信息,被称为严重时间。正好与存储在kml中的地标一样。直接传递字符串没有效果。如果我选​​择设置活动字幕选项( KMLParser中的annotation.subtitle = placemarkDescription,也许我会获取用户点击的注释的字幕信息,但我不想显示此信息,因为它显示为这样

<table width="280px"><tr><td></td><td></td></tr></table><table width="280px"><tr......

顺便说一下,我不知道如何获取所选注释的字幕信息。 到目前为止,我只设法将描述信息存储在一个数组中(在KMLParser.m中完成)。但是我应该怎么处理该数组?如何知道哪个数组条目对应用户点击的注释(注释)已打开标注气泡。)

所以我不知道该怎么做。 也许我不太清楚:我想要做的是获取地标(注释)的描述信息,当用户点击地图中的注释时,点击disclosureButton应该将他重定向到显示描述信息的webView。

编辑代码已添加:

DetailViewController.h

#import <UIKit/UIKit.h>

@interface DetailViewController : UIViewController<UIWebViewDelegate> {
UIWebView               *webView;
UITextField             *addressBar;
UIActivityIndicatorView *activityIndicator;
NSString                *placemarkDescription;
}

@property (nonatomic, retain) IBOutlet UIWebView                *webView;
@property (nonatomic, retain) IBOutlet UITextField              *addressBar;
@property (nonatomic, retain) IBOutlet UIActivityIndicatorView  *activityIndicator;
@property (nonatomic, retain) NSString                              *placemarkDescription;

-(IBAction) gotoAddress:(id)sender;
-(IBAction) goBack:(id)sender;
-(IBAction) goForward:(id)sender;

@end

DetailViewController.m

#import "DetailViewController.h"

@implementation DetailViewController

@synthesize webView, addressBar, activityIndicator, placemarkDescription;

- (void)viewDidLoad {
[super viewDidLoad];

[webView loadHTMLString:placemarkDescription baseURL:nil];

}

 -(IBAction)gotoAddress:(id) sender {
 NSURL *url = [NSURL URLWithString:[addressBar text]];
 NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];

[webView loadRequest:requestObj];
[addressBar resignFirstResponder];
}

-(IBAction) goBack:(id)sender {
[webView goBack];
}

-(IBAction) goForward:(id)sender {
[webView goForward];
}

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request    navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
    NSURL *URL = [request URL]; 
    if ([[URL scheme] isEqualToString:@"http"]) {
        [addressBar setText:[URL absoluteString]];
        [self gotoAddress:nil];
    }    
    return NO;
}   
return YES;   
}

- (void)webViewDidStartLoad:(UIWebView *)webView {
[activityIndicator startAnimating];
}

- (void)webViewDidFinishLoad:(UIWebView *)webView {
[activityIndicator stopAnimating];
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; 
}

- (void)dealloc {
[super dealloc];
}

@end

PlacemarkAnnotation2.h

#import <Foundation/Foundation.h>
#import <MapKit/Mapkit.h>

@interface PlacemarkAnnotation2 : NSObject <MKAnnotation> {

CLLocationCoordinate2D coordinate;
NSString * title;
NSString * subtitle;
NSString * placemarkDescription;
}

@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
@property (nonatomic, retain) NSString * title;
@property (nonatomic, retain) NSString * subtitle;
@property (nonatomic, retain) NSString * placemarkDescription;

@end

PlacemarkAnnotation2.m

#import "PlacemarkAnnotation2.h"

@implementation PlacemarkAnnotation2

@synthesize coordinate, title, subtitle, placemarkDescription;

- (id) initWithCoordinate:(CLLocationCoordinate2D)coord andTitle:(NSString *)maintitle andSubtitle:(NSString *)subTitle {
self.coordinate = coord;
self.title = maintitle;
self.subtitle = subTitle;

return self;
}

-(NSString *) placemarkDescription
{
return placemarkDescription;
}

- (void) setPlacemarkDescription: (NSString *) pd
{
placemarkDescription = pd;
}

- (void) dealloc {
[title dealloc];
[subtitle dealloc];
[placemarkDescription dealloc];

[super dealloc];
}

@end

KMLParser.M中的更改

//KMLPoint class

- (MKShape *)mapkitShape
{

PlacemarkAnnotation2 *annotation = [[PlacemarkAnnotation2 alloc] init];
annotation.coordinate = point;
return [annotation autorelease];
}

//KMLPlacemark class

- (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.

    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;

    mkShape.placemarkDescription = placemarkDescription;
}
}

在这行代码中发现错误(没有崩溃说明原因):

-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view 
calloutAccessoryControlTapped:(UIControl *)control
{
NSLog(@">>> Entering %s <<<", __PRETTY_FUNCTION__);

DetailViewController *dvc = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:[NSBundle mainBundle]];
PlacemarkAnnotation2 *pa = (PlacemarkAnnotation2 *)view.annotation;
dvc.placemarkDescription = pa.placemarkDescription;
[self presentModalViewController:dvc animated:YES];
[dvc release];

NSLog(@"<<< Leaving %s >>>", __PRETTY_FUNCTION__);
}

1 个答案:

答案 0 :(得分:1)

目前尚不清楚您正在使用多少KMLViewer示例应用程序代码,但实现此目的的一种方法是创建自己的注释类,而不是像示例应用程序那样使用MKPointAnnotation类。

自定义类(例如“PlacemarkAnnotation”)应该实现MKAnnotation协议或者是MKShape的子类(如果您使用的是KMLViewer代码)。在自定义类中,添加placemarkDescription属性。

当KMLViewer代码当前创建MKPointAnnotation对象时,请改为创建PlacemarkAnnotation并设置其placemarkDescription属性而不是subtitle属性。

然后在viewForAnnotation委托方法中,将rightCalloutAccessoryView设置为详细披露按钮。

接下来,在项目中添加一个带有UIWebView的详细视图控制器。将placemarkDescription属性添加到视图控制器。在viewDidLoad方法中,在网络视图上调用loadHTMLString并将其传递给placemarkDescription(我认为您可以通过nil传递baseURL

在地图视图的calloutAccessoryControlTapped委托方法中,创建详细视图控制器,设置其placemarkDescription属性并显示它:

-(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];
}


修改

首先,看起来最好将MKShape子类化为自定义类,而不是实现MKAnnotation协议。 KMLViewer代码的其余部分基于这个假设。因此,将@interface PlacemarkAnnotation2 : NSObject <MKAnnotation>更改为@interface PlacemarkAnnotation2 : MKShape。 (顺便说一句,对于NSString属性,copyretain更合适,它会消除警告。)

您可能已将mkShape(和其他地方)中的KMLPlacemark ivar的类型从MKShape更改为其他内容。将这些类型更改回MKShape

接下来,_createShape可能不是设置placemarkDescription的最佳位置,因为为覆盖和注释调用了该方法。从该方法中删除您的更改,并将其放在point方法中(也在KMLPlacemark中)。请注意,您的更改可能存在一些与内存相关的问题。这是我的建议:

- (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;
}