トップ «前の日記(2012-04-30) 最新 次の日記(2012-05-02)» 編集

Cocoa練習帳

iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど

2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|

2012-05-01 [iOS][Web]iPhoneアプリケーションとサーバ間の通信(その4)

先日のRESTの回では、取得したXMLデータを解析していなかったので、今回は、解析に挑戦だ。

XMLデータへのアクセス方法には、DOMとSAXの2種類があるが、iOSではCocoaのフレームワークで用意されているのはSAXに対応するNSXMLParserのみだ。もちろん、DOMも利用できるか、Cocoaのフレームワークなので手軽だという事と、iOS機器の貧弱なリソース(メモリetc)を考えて、NSXMLParserを利用する方法を紹介する。

ビー・コントローラーにNSXMLParserDelegateプロトコルを追加し、解析で使用するプロパティを追加する。

@interface ViewController : UIViewController <NSXMLParserDelegate>
	...
@property (assign, nonatomic) BOOL                  inPersonElement;
@property (assign, nonatomic) BOOL                  inNameElement;
@property (assign, nonatomic) BOOL                  inAgeElement;
@property (strong, nonatomic) NSMutableString       *name;
@property (strong, nonatomic) NSMutableString       *age;
	...
@end

返ってきたデータdataをパースする。ARCのおかげで、記述が簡素になっている。

        if (data) {
            NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:data];
            xmlParser.delegate = self;
            [xmlParser parse];
        }

パースで利用する、委任メソッドだ。

- (void)parserDidStartDocument:(NSXMLParser *)parser
{
    self.inPersonElement = NO;
    self.inNameElement = NO;
    self.inAgeElement = NO;
}
 
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
}
 
- (void)parser:(NSXMLParser *)parser
    didStartElement:(NSString *)elementName
    namespaceURI:(NSString *)namespaceURI
    qualifiedName:(NSString *)qualifiedName
    attributes:(NSDictionary *)attributeDict
{
    if ([elementName isEqualToString:@"person"]) {
        self.inPersonElement = YES;
    }
    else if ([elementName isEqualToString:@"name"]) {
        self.inNameElement = YES;
        self.name = [[NSMutableString alloc] init];
    }
    else if ([elementName isEqualToString:@"age"]) {
        self.inAgeElement = YES;
        self.age = [[NSMutableString alloc] init];
    }
}
 
- (void)parser:(NSXMLParser *)parser
    didEndElement:(NSString *)elementName
    namespaceURI:(NSString *)namespaceURI
    qualifiedName:(NSString *)qName
{
    if ([elementName isEqualToString:@"person"]) {
        self.inPersonElement = NO;
        NSLog(@"person(name[%@], age[%@])", self.name, self.age);
    }
    else if ([elementName isEqualToString:@"name"]) {
        self.inNameElement = NO;
    }
    else if ([elementName isEqualToString:@"age"]) {
        self.inAgeElement = NO;
    }
}
 
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    if (self.inPersonElement) {
    }
     
    if (self.inNameElement) {
        [self.name appendString:string];
    }
    else if (self.inAgeElement) {
        [self.age appendString:string];
    }
}

NSXMLParserで解析する場合、ステータスを覚えておいて、ステータスに合わせて得られた情報を扱う必要があるが、この程度の簡素なデータでは、特に問題はないと思う。

_ ソースコード

GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/ios/REST - GitHub

トップ «前の日記(2012-04-30) 最新 次の日記(2012-05-02)» 編集