了解iOS中的NSXMLParser

我学习了当前的NSXMLParser。 我读了很多教程,但没有人能告诉我它是如何工作的。 有一个关于StackOverflow的教程? 我的问题是这个KML读取结构在我的应用程序,并显示与MKMapView

我的parsing器类看起来像:

#import <Foundation/Foundation.h> @interface Parser : NSXMLParser @property (nonatomic, strong) NSString *rowElementName; // this is the element name that identifies a new row of data in the XML @property (nonatomic, strong) NSArray *attributeNames; // this is the array of attributes we might want to retrieve for that element name @property (nonatomic, strong) NSArray *elementNames; // this is the list of sub element names for which we're retrieving values @property (nonatomic, strong) NSMutableArray *items; // after parsing, this is the array of parsed items @end 

 #import "Parser.h" @interface Parser () <NSXMLParserDelegate> @property (nonatomic, strong) NSMutableDictionary *item; // while parsing, this is the item currently being parsed @property (nonatomic, strong) NSMutableString *elementValue; // this is the element within that item being parsed @end @implementation Parser - (id)initWithContentsOfURL:(NSURL *)url { self = [super initWithContentsOfURL:url]; if (self) { self.delegate = self; } return self; } - (id)initWithData:(NSData *)data { self = [super initWithData:data]; if (self) { self.delegate = self; } return self; } - (id)initWithStream:(NSInputStream *)stream { self = [super initWithStream:stream]; if (self) { self.delegate = self; } return self; } #pragma mark - NSXMLParserDelegate methods - (void)parserDidStartDocument:(NSXMLParser *)parser { self.items = [[NSMutableArray alloc] init]; if (!self.rowElementName) NSLog(@"%s Warning: Failed to specify row identifier element name", __FUNCTION__); } - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict { if ([elementName isEqualToString:self.rowElementName]) { self.item = [[NSMutableDictionary alloc] init]; for (NSString *attributeName in self.attributeNames) { id attributeValue = [attributeDict valueForKey:attributeName]; if (attributeValue) [self.item setObject:attributeValue forKey:attributeName]; } } else if ([self.elementNames containsObject:elementName]) { self.elementValue = [[NSMutableString alloc] init]; } } - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { if (self.elementValue) { [self.elementValue appendString:string]; } } - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { if ([elementName isEqualToString:self.rowElementName]) { [self.items addObject:self.item]; self.item = nil; } else if ([self.elementNames containsObject:elementName]) { [self.item setValue:self.elementValue forKey:elementName]; self.elementValue = nil; } } @end 

由rob创build

我的XML文件:

 <?xml version="1.0" encoding="UTF-8"?> <kml xmlns="http://earth.google.com/kml/2.1"> <Document> <name>Filename.kml</name> <Style id="style1"> <IconStyle> <Icon> <href>http://imageshack.us/a/img825/9079/pinvi.png</href> </Icon> </IconStyle> </Style> <Placemark> <name><![CDATA[Blankenese]]></name> <Snippet><![CDATA[Blankeneser Bahnhofstr. 9 22587 Hamburg +49-(0)40-866 06 50 +49-(0)40-86 60 65 60]]></Snippet> <description><![CDATA[<img src="http://www.engelvoelkers.com/shops/de-blankenese-res.jpg"><br/>Blankeneser Bahnhofstr. 9<br/>22587 Hamburg<br/>Telefon: +49-(0)40-866 06 50<br/>Fax: +49-(0)40-86 60 65 60<br/><a href="http://www.engelvoelkers.com/elbe">Website</a><br/>E-Mail: Blankenese@engelvoelkers.com]]></description> <styleUrl>#style1</styleUrl> <Point> <coordinates>9.811470,53.559441</coordinates> </Point> </Placemark> </Document> </kml> 

我的目标是获取<description>标记中的所有信息,并像谷歌地图一样显示它 在这里输入图像说明

不完全相似。

但首先我需要知道我可以如何与parsing器合作

最好的问候CTS

这个问题有两个根本不同的组成部分,parsing和注释地图。 我将在这里专注于地图注释,因为我想我在这里覆盖了parsing问题: 尝试在MKMapView中加载创build的Map 。 不过,在这个答案的最后,我还提到了一些对苹果parsing文档的引用,如果你只是试图围绕着NSXMLParser

注释地图

在iPhone上绘制应用程序的常见模式是在地图视图本身不显示丰富的内容的popup式窗口,而是由于iPhone的有限的房地产,只显示标准的标注,而是将rightCalloutAccessoryView设置为公开的指标,如果你点击它,将继续下一个视图的细节。 因此,通过使用UIMapViewDelegate方法,你可以有一个mapView:viewForAnnotation:它说:

 - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation { MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"loc"]; annotationView.canShowCallout = YES; annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; return annotationView; } 

这会产生以下用户界面:

正确的标注配件

然后你可以有一个mapView:annotationView:calloutAccessoryControlTapped:就像这样:

 - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control { [self performSegueWithIdentifier:@"DetailsIphone" sender:view]; } 

您可以使用它来转到您的详细信息屏幕。 (我只是做一个模式segue视图控制器与Web视图,在prepareForSegue传递注释,并viewDidLoad是抓住HTML等,这里的细节不起眼,我假设你可以过渡到自己的细节屏幕和devise比这个快速和肮脏的网页视图漂亮的东西…我只是表明,我们可以抓住从KML文件的地标的HTML):

iPhone细节屏幕

所以,虽然iPhone真的不应该在地图本身,在iPad上使用popup,你可以使用它们。 你可以用类似的方式创buildrightCalloutAccessoryView (虽然也许使用“info”button而不是详细的内容):

iPad右侧标注配件

但在这里你可以有mapView:annotationView:calloutAccessoryControlTapped:实际上生成mapView:annotationView:calloutAccessoryControlTapped:而不是做模态转换:

 - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control { //CGRect frame = view.frame; [mapView deselectAnnotation:view.annotation animated:YES]; DetailsViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"DetailsPopover"]; controller.annotation = view.annotation; self.popover = [[UIPopoverController alloc] initWithContentViewController:controller]; self.popover.delegate = self; [self.popover presentPopoverFromRect:view.frame inView:view.superview permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; } 

这产生:

iPad popover

顺便说一下,这大概接近iPad地图应用程序如何做(当你点击一个别针,它显示一个标有“信息”button的标注),如果你然后点击信息button,它显示你popover与细节。

另外,你也可以点击销钉,直接跳到你的popup窗口,绕过插入的标注。 为此,您首先必须禁用注释视图本身的标注:

 - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation { MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"loc"]; annotationView.canShowCallout = NO; return annotationView; } 

但是你必须回应mapView:didSelectAnnotationView: ::

 - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view { [mapView deselectAnnotation:view.annotation animated:YES]; DetailsViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"DetailsPopover"]; controller.annotation = view.annotation; self.popover = [[UIPopoverController alloc] initWithContentViewController:controller]; self.popover.delegate = self; [self.popover presentPopoverFromRect:view.frame inView:view.superview permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; } 

理论上,你可以在iPhone上做这样的事情,但是由于你不能使用UIPopoverController ,所以你必须使用一些第三方的UIPopoverController (或者自己写)。 我听说一些人声称,苹果已经拒绝iPhone应用程序使用popover的意见,虽然我既不能确认,也没有说这是否是一个硬性规定。 我只知道,苹果和谷歌的iPhone地图应用程序不会在iPhone地图应用程序上使用大的弹窗视图(苹果会继续看另一个视图,谷歌已经出现在屏幕的底部)。 如果你仔细想想,如果这个引脚正好在中间位置,并且你试图产生一个指向这个引脚的大popup,它可能会变得局促。

无论如何,这些是使用rightCalloutAccessoryView设置和/或禁用canShowCallout并直接显示rightCalloutAccessoryView的选项。


parsing引用:

  • Apple 事件驱动的XML编程指南
  • NSXMLParser类参考

地图视图标注参考:

  • 自定义MKAnnotation标注泡泡

parsing器像这样工作,打开根标签,然后search子标签。 当没有更多的嵌套标签的数据被读取,在这里你可以有一个选项,你想如何保存你的数据。 还有许多其他的parsing器可用。 通过gDataXMLParser。 我已经使用它,工作得很好,确保recursion调用parsing器,如果有嵌套标记。 如果你正在寻找一个特定的标签,使用string来查找子string,即;从<b></b>这样的东西,并阅读其中的文字。