6

現在の NSXMLParser について学びます。多くのチュートリアルを読みましたが、それがどのように機能するかを正確に教えてくれるものはありませんでした. StackOverflow に関するチュートリアルはありますか? 私の問題は、アプリでこの KML 読み取り構造を読み取り、MKMapView で表示することです

私のパーサークラスは次のようになります。

#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

ロブによって作成された

私の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 マップのように表示することです。ここに画像の説明を入力

正確ではありませんが、似ています。

しかし、最初にパーサーの操作方法を知る必要があります

よろしくお願いしますCTS

4

2 に答える 2

16

この質問には、マップの解析と注釈付けという 2 つの根本的に異なるコンポーネントがありました。解析に関する質問はここで説明したと思うので、ここではマップの注釈に焦点を当てます: Try to load a created Map in MKMapView . ただし、この回答の最後に、腕を動かそうとしているだけの場合は、Apple の解析ドキュメントへの参照をいくつか含めますNSXMLParser

地図に注釈を付ける

iPhone のマッピング アプリの一般的なモデルは、マップ ビュー自体にリッチ コンテンツを含むポップオーバーを表示するのではなく、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 ビューを使用してビュー コントローラーにモーダル セグエを実行し、注釈を に渡し、prepareForSegueviewDidLoadhtml を取得するなどしています。ここでの詳細は目立たないものです。独自の詳細画面に遷移して、この簡単で汚い Web ビューよりもきれいなものを設計してください... KML ファイルから目印の HTML を取得できることを示しているだけです):

iPhoneの詳細画面

したがって、iPhone では地図自体にポップオーバーを使用するべきではありませんが、iPad では使用できます。同様の方法でを作成できますrightCalloutAccessoryView(ただし、詳細開示ではなく「情報」ボタンを使用することもできます)。

iPad 右吹き出しアクセサリ

しかし、ここでは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 ポップオーバー

ちなみに、これは iPad マップ アプリの動作とほぼ同じです (ピンをクリックすると、「情報」ボタン付きのコールアウトが表示されます)。情報ボタンをクリックすると、ポップオーバーが表示されます。詳細とともに。

または、ピンをクリックすると、介在する吹き出しをバイパスして、ポップオーバーに直接移動することができます。ただし、これを行うには、まず、注釈ビュー自体の吹き出しを無効にする必要があります。

- (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、サードパーティのポップオーバーを使用する (または独自に作成する) 必要があります。Apple がポップオーバー ビューを使用する iPhone アプリを拒否したと主張する人がいると聞いたことがありますが、私はそれを確認することも、それが厳格なルールであるかどうかもわかりません。Apple と Google の iPhone マッピング アプリは、iPhone マップ アプリで大きなポップオーバー ビューを使用していないことだけは知っています (Apple は別のビューに切り替え、Google は画面の下部に表示します)。考えてみれば、ピンがちょうど真ん中にあり、そのピンを指す大きなポップオーバーを生成しようとすると、窮屈になるかもしれません。

とにかく、これらは設定を使用したり、ポップオーバーを直接rightCalloutAccessoryView無効にして表示したりするためのオプションです。canShowCallout


参照の解析:

マップ ビューのコールアウト リファレンス:

于 2013-01-31T05:53:37.910 に答える
1

パーサーは次のように動作します。ルート タグが開かれ、サブ タグが検索されます。ネストされたタグがなくなると、データが読み込まれ、ここでデータを保存する方法を選択できます。他にも多くのパーサーが利用可能です。gDataXMLParser を通過します。私はそれを使用しており、かなりうまく機能し、ネストされたタグがある場合はパーサーを再帰的に呼び出すようにしてください。特定のタグを探している場合は、文字列を使用して部分文字列 ie;From を検索し、<b>その</b>中のテキストを読み取ります。

于 2013-01-30T16:27:43.660 に答える