问题描述
在我的应用程序中,我使用 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 = @"<";
NSString *greaterThan = @">";
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
属性,copy
比 retain
更合适,它会消除警告.)
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 = @"<";
NSString *greaterThan = @">";
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 副标题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!