NSRangeとは?
NSRangeはlocation(位置)とlength(長さ)の2つを持つ、"範囲"を表す構造体です。文字列の検索、分割、切り出し等に重宝します。
※2013/06/11 正規表現検索のサンプルを追加
例えば以下のようにrangeOfStringメソッドを使うと、
"列です"という文字列が最初に現れた「位置」と「長さ」をNSRangeという「範囲」で取得することができます。
NSString *text = @"テスト用の文字列です 2012/8/13";
NSRange rangeTest = [text rangeOfString:@"列です"];
検索に失敗した時
検索した文字列が見つからない時は、NSNotFoundという値がlocationに返却されるので、if(range.location == NSNotFound)のように条件に使えます。
パフォーマンスについて
以下メソッドでoptionにNSLiteralSearchを指定する事で、検索のパフォーマンスが大分変わるようです。
rangeOfString:(NSString *)aString options:(NSStringCompareOptions)mask
オプションはOR演算で組み合わせ可能です。
NSStringCompareOptions options = NSLiteralSearch | NSCaseInsensitiveSearch;
尚、NSLiteralSearch指定のみなら早くなりますが、合成文字を無視する事、
組み合わせによりむしろ遅くなる事があるので注意が必要です。
NSRegularExpressionSearchと組み合わせたら3倍程時間かかってました。
参考:http://blog.fenrir-inc.com/jp/2013/04/stringfind-options.html
以下はサンプルコードです。ご参考までに。
// NSRangeのテスト用の文字列を準備 NSString *text = @"テスト用の文字列です 2012/8/13"; // 画像と同様のNSRangeのテスト NSRange rangeTest = [text rangeOfString:@"列です"]; NSLog(@"rangeTestのrangeは%@",NSStringFromRange(rangeTest)); // 「12」という文字列が最初に現れる場所を検索し、位置と長さを持つNSRange構造体を取得する。 NSRange range1 = [text rangeOfString:@"12"]; NSLog(@"range1のlocationは%lu",range1.location); // 検索した文字列が存在しない時、range.locationにはlongの最大値が返却される。 NSRange range2 = [text rangeOfString:@"9"]; NSLog(@"range2のlocationは%lu",range2.location); // 検索対象が空文字だった場合も、range.locationにはlongの最大値が返却される。 NSString *emptyText = @""; NSRange rangeEmpty = [emptyText rangeOfString:@"aaa"]; NSLog(@"rangeEmptyのlocationは%lu",rangeEmpty.location); // 検索対象がnilだった場合は、0が返却されます。 // Objective-Cではnilへのメッセージは無視されますが、 // 戻り値があるメソッドは0が返却されます。 NSString *nilText = nil; NSRange rangeNil = [nilText rangeOfString:@"aaa"]; NSLog(@"rangeNilのlocationは%lu",rangeNil.location); // [実行結果] // rangeTestのrangeは{7, 3} // range1のlocationは13 // range2のlocationは9223372036854775807 // rangeEmptyのlocationは9223372036854775807 // rangeNilのlocationは0 // 検索対象が空文字だった時、検索した文字列が存在しない場合に返却される値は、 // long型の最大値LONG_MAXを定数化したNSIntegerMaxをenumで再定義したNSNotFoundなので、 // 検索対象が見つからなかったらxxするという条件に、以下のようにNSNotFoundを利用することができる。 if (range2.location == NSNotFound) { NSLog(@"rangeOfStringで検索対象が見つからなかった時の処理。"); } // rangeを作りたい場合はNSMakeRangeを使う、例えば先頭から3文字の切り出し NSRange rangeZeroTo3 = NSMakeRange(0, 3); NSString *fst3Str = [text substringWithRange:rangeZeroTo3]; NSLog(@"%@",fst3Str); // [実行結果] // テスト // 正規表現による検索、以下文字列から「2013年」を探す。 // 変数を正規表現に含めたい時はstringWithFormatで%@を使う。 NSString *searchTarget = @"先日行われた2013年のWWDCはiOS7の発表がありました。"; NSString *suffixJapaneaseYear = @"年"; NSString *regexStr = [NSString stringWithFormat:@"[0-9]{1,4}%@",suffixJapaneaseYear]; NSRange resultRange = [searchTarget rangeOfString:regexStr options:NSRegularExpressionSearch]; NSLog(@"検索結果は%@です。",[searchTarget substringWithRange:resultRange]); // [実行結果] // 検索結果は2013年です。 // 100万回の検索でNSLiteralSearchを指定 NSLog(@"start"); NSString *ret; NSString *searchTarget2 = @"先日行われた2013年のWWDCはiOS7の発表がありました。"; NSString *japaneaseYear = @"年"; for (int i = 0; i < 10000000; i++) { // 以下コメントを切り替えて比較 NSRange resultRange = [searchTarget2 rangeOfString:japaneaseYear]; //NSRange resultRange = [searchTarget rangeOfString:japaneaseYear options:NSLiteralSearch]; ret = [searchTarget2 substringWithRange:resultRange]; } NSLog(@"end 検索結果は%@です。",ret);
[参考サイト]
・文字列からある文字列が含まれる全てのNSRangeを取得する。(stackoverflow)
http://stackoverflow.com/questions/8533691/how-to-get-all-nsrange-of-a-particular-character-in-a-nsstring
・任意の文字が現れる場所を確認する
http://program.station.ez-net.jp/special/handbook/objective-c/nsstring/range-of-string.asp