Help us understand the problem. What is going on with this article?

NSScanner NSStringを探索する

More than 5 years have 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処理)していく用途で使いやすいかと思います。
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away