Относительно Apple KMLViewer метка описания и субтитров аннотации - PullRequest
1 голос
/ 27 ноября 2011

В моем приложении я использую KMLViewer от Apple для отображения аннотаций, которые я получаю из файла KML. В файле KMLParser.m есть переменная экземпляра placemarkDescription, которая преобразует информацию в тегах Description из файла kml в аннотацию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.mi преобразовали 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. Поэтому передача строки напрямую не имеет никакого эффекта. Если я выбираю активную опцию субтитров (annotation.subtitle = placemarkDescription в KMLParser), может быть, я получу информацию о субтитрах аннотации, которую коснулся пользователь, но я не хочу показывать эту информацию, потому что она выглядит следующим образом

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

Кстати, японятия не имею, как получить информацию о субтитрах выбранной аннотации.До сих пор мне удавалось только хранить информацию описания в массиве (это делается в KMLParser.m). Но что мне делать с этим массивом? Как узнать, какой записи массива соответствует аннотация, которую пользователь нажал (аннотация)у него открыт пузырь выноски).

Так что я не знаю, что делать.Может быть, я не слишком ясно: что я хочу сделать, это получить информацию Описание метки (аннотации), когда пользователь нажимает аннотацию на карте, нажатие кнопки disclosureButton должно перенаправить его в веб-представление, отображающее описание информации.

РЕДАКТИРОВАТЬ код Добавлено:

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 Ответ

1 голос
/ 28 ноября 2011

Не ясно, сколько кода примера приложения 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 свойств copy более подходит, чем retain, и он избавится от предупреждений.)

Похоже, вы также изменили типmkShape ивара в KMLPlacemark (и других местах) от 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;
}
...