了解iOS中的NSXMLParser

前端之家收集整理的这篇文章主要介绍了了解iOS中的NSXMLParser前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我了解了当前的NS XMLParser.我阅读了很多教程,但没有人能告诉我它是如何工作的. StackOverflow上有一个教程?我的问题是我的应用程序中的KML读取结构,并使用MKMapView进行显示

我的Parser类看起来像:

#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创建

我的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>中的所有信息.标记显示它像Google-Maps一样

不完全但是相似.

但首先我需要知道如何与Parser一起工作

最好的问候CTS

解决方法

这个问题有两个根本不同的组件,解析和注释地图.我将重点关注这里的地图注释,因为我认为我在这里讨论了解析问题: Try to load a created Map in MKMapView.但是,在这个答案的最后,如果你只是试图搂着它,我会包含对Apple解析文档的一些引用.的NSXMLParser.

注释地图

在iPhone上映射应用程序的常见模型是不在地图视图本身上显示具有丰富内容的popover,而是由于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];
}

您可以使用它来转到您的详细信息屏幕. (我只是对带有Web视图的视图控制器进行模态转换,在prepareForSegue中传递注释,viewDidLoad正在抓取html等.此处的详细信息不起眼.我假设您可以转换到您自己的详细信息屏幕和设计比这个快速和脏的Web视图更漂亮……我只是在演示我们可以从KML文件获取地标的HTML):

因此,虽然iPhone真的不应该在地图上使用弹出窗口,但在iPad上,你可以使用它们.您可以以类似的方式创建rightCalloutAccessoryView(尽管可能使用“info”按钮而不是详细信息披露):

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

- (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 Maps应用程序的工作方式(当你点击一个图钉时,它会显示一个带有“信息”按钮的标注),如果你点击信息按钮,它会显示你的弹出窗口有详细信息.

或者,您可以点击引脚直接转到弹出窗口,绕过介入的标注.但是,要做到这一点,首先必须在注释视图上禁用标注:

- (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,你必须使用一些第三方popover(或自己编写).我听说有些人声称Apple拒绝使用popover视图的iPhone应用程序,虽然我既不能确认,也不能说这是否是一个硬性规则.我只知道Apple和谷歌iPhone地图应用程序不会在iPhone地图应用程序上使用大型弹出窗口视图(Apple转向另一种视图,Google将其显示在屏幕底部).如果你考虑一下,如果针脚在中间位置并且你试图生成一个指向该针脚的大型弹出窗口,它可能会变得狭窄.

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

解析参考文献:

> Apple Event-Driven XML Programming Guide
> NSXMLParser Class Reference

地图视图标注参考:

> Customizing the MKAnnotation Callout bubble

猜你在找的iOS相关文章