NSScanner NSStringを探索する

  • 33
    Like
  • 0
    Comment
More than 1 year has passed since last update.

NSScannerはNSStringを探索するクラスです。
正規表現やNSStringとは違った文字列の探索が出来ます。

ざっとした概要

NSScannerは位置(scanLocation)を保持しています。
各メソッドで位置を進めつつ順次探索することが出来ます。

例1 URLのクエリパラメーターを取得

@"text=aiueo&query=search&target=ea

query に対応する文字列を取得します。

Sample.m
NSScanner *scanner = [NSScanner scannerWithString:@"text=aiueo&query=search&target=ea"];

// 「query=」を見つけるまで探索する。scannerは「q」の位置に進む
[scanner scanUpToString:@"query=" intoString:nil];

// 現在の位置(q)から「query=」を探索する。scannerは「s」の位置に進む
[scanner scanString:@"query=" intoString:nil];

NSString *resultStr;
// 現在の位置(s)から「&」を見つけるまで探索する。scannerはtargetの1つ前の「&」の位置に進む
//「s」の位置から「&」を見つけるまで探索した結果がresultStrに割り当てられる
[scanner scanUpToString:@"&" intoString:&resultStr];
NSLog(@"%@", resultStr); // search

例2 数値を取得

@"abcd123456"

文字列に含まれる数値を取得します。

Sample.m
NSScanner *scanner = [NSScanner scannerWithString:@"abcd123456"];
// 無視するキャラクターセットを設定(アルファベットの小文字)
[scanner setCharactersToBeSkipped:[NSCharacterSet lowercaseLetterCharacterSet]];
NSInteger integer = 0;
// 先頭から数値を探索(アルファベットは無視される)
[scanner scanInteger:&integer];
NSLog(@"%d", integer); // 123456

例3 全ての数字を取得

@"abcd123EFg456"

アルファベットと数字が混在する文字列から全ての数字を取得します。

Sample.m
NSScanner *scanner = [NSScanner scannerWithString:@"abcd123EFg456"];
NSMutableString *mStr = [NSMutableString string];
// 無視するキャラクターセットを設定(アルファベットの大文字・小文字)
[scanner setCharactersToBeSkipped:[NSCharacterSet letterCharacterSet]];
// 文字列の末尾に到達するまで探索を繰り返す
while (scanner.isAtEnd == NO) {
    // 先頭から数値を探索(アルファベットは無視される)
    [scanner scanInteger:&integer];
    [mStr appendFormat:@"%d", integer];
}
NSLog(@"%@", mStr); // 123456

カテゴリ

例1をしやすいようにNSScannerのカテゴリに実装しました。

NSScanner+Extras.h
@interface NSScanner (Extras)

+ (void)extractStringWithAllString:(NSString*)allStr startString:(NSString*)startStr endString:(NSString*)endStr result:(void(^)(NSString*))result;

@end
NSScanner+Extras.m
#import "NSScanner+Extras.h"

@implementation NSScanner (Extras)

+ (void)extractStringWithAllString:(NSString*)allStr startString:(NSString*)startStr endString:(NSString*)endStr result:(void(^)(NSString*))result
{
    NSScanner *scanner = [NSScanner scannerWithString:allStr];
    [scanner scanUpToString:startStr intoString:nil];
    [scanner scanString:startStr intoString:nil];
    [scanner scanUpToString:endStr intoString:&resultStr];
    result(resultStr);
}

@end
Sample.m
[NSScanner extractStringWithAllString:@"text=aiueo&query=search&target=ea"
                          startString:@"query="
                            endString:@"&"
                               result:^(NSString *resultStr){
                                   NSLog(@"%@", resultStr); // search
                               }];    

まとめ

  • 例1や3のような順次取得(or処理)していく用途で使いやすいかと思います。