关于 Apple 的 KMLViewer placemarkDescription 和 annotation 副标题 [英] Regarding Apple's KMLViewer placemarkDescription and annotation subtitle

查看:15
本文介绍了关于 Apple 的 KMLViewer placemarkDescription 和 annotation 副标题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序中,我使用 Apple 的 KMLViewer 来显示我从 KML 文件中获得的注释.在文件 KMLParser.m 中,有一个实例变量 placemarkDescription 用于转换描述标签下的信息从kml文件到注释副标题.现在,在我的文件中,每个注释都以这种方式存储在描述下的信息:

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 that converts the information under Description tags from kml file to annotation subtitle.Now, in my file every annotation has the information stored under Description in this way:

<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 从那个转换成这个:

In KMLParser.m i have transformed the placemarkDescription from that to this:

<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中的地标的次数完全一样.所以直接传递字符串没有效果.如果我选​​择激活字幕选项(annotation.subtitle = placemarkDescription in KMLParser),也许我会得到用户点击的注释的字幕信息,但我不想显示这些信息,因为它是这样显示的

I've done this because I want to pas this string to a webView and visualize this in it. The problem is that when the kml loads, the methods get the description information, get called severe times.Exactly as times as placemarks stored in the kml.So passing the string directly has no effect.If i choose to set active the subtitle option (annotation.subtitle = placemarkDescription in KMLParser), maybe I gen get the subtitle info of the annotation the user tapped, but I don't want to show this information because it shows like this

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

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

By the way, I don't have any idea of how to get the subtitle info of the selected annotation. So far, I have managed only to store the description information in an array (done this in the KMLParser.m).But what should I do with that array?How to know to which array entry corresponds the annotation the user tapped (the annotation that has the callout bubble opened).

所以我不知道该怎么办.可能我没说太清楚:我想要做的是获取一个地标(annotation)的Description信息,当用户点击地图中的annotation时,点击disclosureButton应该会将他重定向到一个显示描述信息的webView.

So I don't know what to do. Maybe I have not been too clear: What I want to do is get the Description information of a placemark (annotation), when the user taps an annotation in the map, tapping the disclosureButton should redirect him to a webView that shows the description Information.

编辑代码添加:

DetailViewController.h

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

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

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

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 中的变化

Changes in 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;
}
}

在这行代码中发现错误(无崩溃原因描述):

Error found in this lines of code (No cause of crash description):

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

推荐答案

不清楚您使用了多少 KMLViewer 示例应用代码,但一种方法是创建您自己的注释类,而不是使用 MKPointAnnotation 类与示例应用程序一样.

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.

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

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.

在 KMLViewer 代码当前创建一个 MKPointAnnotation 对象的地方,创建一个 PlacemarkAnnotation 并设置它的 placemarkDescription 属性而不是 subtitle 属性.

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

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

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

接下来,将一个带有 UIWebView 的细节视图控制器添加到项目中.将 placemarkDescription 属性添加到视图控制器.在 viewDidLoad 方法中,在 web view 上调用 loadHTMLString 并传递它 placemarkDescription (我认为你可以传递 nil对于 baseURL).

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

在地图视图的calloutAccessoryControlTapped委托方法中,创建细节视图控制器,设置它的placemarkDescription属性并呈现它:

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


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

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

看起来您可能已经将 KMLPlacemark(和其他位置)中的 mkShape ivar 的类型从 MKShape 更改为其他类型.将这些类型改回 MKShape.

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.

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

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

这篇关于关于 Apple 的 KMLViewer placemarkDescription 和 annotation 副标题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆