NSArray
初期化
リテラル記法
NSArray *array = @[@"abc", @"def", @"ghi", @"jkl"]; NSLog(@"%@", array); NSLog(@"count: %ld", array.count); NSLog(@" 0: %@", array[0]); NSLog(@" 1: %@", array[1]); NSLog(@" 2: %@", array[2]); NSLog(@" 3: %@", array[3]);
変数を使ったリテラル記法
// リテラル記法は、変数を並べて書ける NSString *a = @"こんにちわ"; NSString *b = @"おやすみなさい"; NSArray *array2 = @[a, b]; NSLog(@"%@", array2);
ネストした配列
NSArray *array3 = @[@"ABC", @[@"GHI", @"JKL"], @"DEF",@"こんにちわ"]; for (int i = 0; i < array3.count; i++) { NSLog(@"%d: %@", i, array3[i]); }
浅いコピー
// flag がYESのときに、各要素をコピーして初期化 BOOL flag = YES; NSArray *array5 = [[NSArray alloc] arrayWithArray:array3 copyItems:flag]; NSLog(@"copied: %@", array5); NSLog(@"address: %p vs %p", array3[0], array5[0]);
アクセス
NSArray *array = @[@"abc", @"def", @"ghi", @"jkl"]; NSLog(@"original array: %@", array);
要素数
NSLog(@"count: %ld", array.count);
要素の位置を取得
NSString *anObject = @"ghi"; NSUInteger index = NSNotFound; index = [array indexOfObject:anObject]; if (index != NSNotFound) { NSLog(@"%@ found at %ld", anObject, index); } else { NSLog(@"%@ not found", anObject); }
要素を持っているか?
BOOL doesContainTheObject = NO; doesContainTheObject = [array containsObject:@"def"]; NSLog(@"Does contain? %@", doesContainTheObject ? @"YES!" : @"NO.");
要素の取り出し
for (NSUInteger ui = 0 ; ui < array.count; ui++) { NSLog(@"index %lu: %@", (unsigned long)ui, [array objectAtIndex:ui]); }
最後の要素
// レンジの表す範囲のオブジェクトを、Cの配列へコピー。その配列の宣言に注目。 void *anObject1; anObject1 = (__bridge void *)([array lastObject]); NSLog(@"last object: %@", anObject1);
NSRange の範囲にある配列を取り出す
NSRange aRange = NSMakeRange(1, 2); // ただのaBuffer単数ではダメで、複数見つかる可能性があるから、配列で渡す。 __unsafe_unretained id aBuffer[ sizeof(id) * aRange.length];
[array getObjects:aBuffer range:aRange]; for (int i = 0; i < aRange.length; i++ ) { NSLog(@"objects: %@", aBuffer[i]); }
NSRange aRange2 = NSMakeRange(0, 3); NSLog(@"sub-array: %@", [array subarrayWithRange:aRange2]); }
配列の比較、追加
配列同士が完全一致
// 格納している要素が同じで、同じインデックス位置にある要素が同じである。 NSArray *array1 = @[@"abc", @"def", @"ghi", @"jkl"]; NSArray *array2 = @[@"abc", @"def", @"ghi", @"jkl"]; NSArray *array3 = @[@"abc", @"def", @"GHI", @"jkl"]; BOOL areEqual;
areEqual = [array1 isEqualToArray: array2]; NSLog(@"1 and 2 are equal? %@", areEqual ? @"YES!" : @"No."); areEqual = [array1 isEqualToArray: array3]; NSLog(@"1 and 3 are equal? %@", areEqual ? @"YES!" : @"No.");
2つの配列の和集合で、最初に見つかったオブジェクト
NSArray *array4 = @[@"JKL", @"ghi"]; __unsafe_unretained id firstObject; // ここが難しかった。 //得られるのは1つのオブジェクトだから、単数(配列ではない)オブジェクト。
firstObject = [array1 firstObjectCommonWithArray:array4]; NSLog(@"first object: %@", firstObject);
新たな要素の追加した新しい配列
NSLog(@"%@", [array1 arrayByAddingObject: @"123"]); NSLog(@"%@", [array1 arrayByAddingObjectsFromArray:@[@"123", @"456"]]); NSLog(@"%@", [@[@"123", @"456"] arrayByAddingObjectsFromArray:array1]);
ソート
セレクタを用いたソート
NSLog(@"sorted by selector(compare:): %@", [anArray sortedArrayUsingSelector:@selector(compare:)] );
関数(ポインタ)を用いて、ソート
{ // 関数の定義。ブロックの外で定義する。 NSComparisonResult compareFunction (__strong id leftObj, __strong id rightObj, void *aContext) {
NSString *leftString = leftObj; NSString *rightString = rightObj;
NSUInteger lengthOfLeftString = leftString.length; NSUInteger lengthOfRightString = rightString.length;
if ( lengthOfLeftString < lengthOfRightString) { return NSOrderedAscending;
} else if ( lengthOfLeftString > lengthOfRightString ) { return NSOrderedDescending;
} else { // same length // compare each character step by step for (int i = 0 ; i <= lengthOfRightString; i++ ) { unichar leftChar = [leftString characterAtIndex:i]; unichar rightChar = [rightString characterAtIndex:i];
if (leftChar < rightChar ) { return NSOrderedAscending; } else if ( leftChar > rightChar ) { return NSOrderedDescending; } // if ends
} // for ends } // if ends
return NSOrderedSame; } //
NSComparisonResult (*compareFunction)(__strong id, __strong id, void *);
void *aContext = NULL; // 関数への第三引数、任意。これを使って比較動作を細かく設定できる、いわばパラメータ。
NSArray *sortedArray2 = [anArray sortedArrayUsingFunction:compareFunction context:aContext];
NSLog(@"sorted by C-type function:"); for (NSString *aStr in sortedArray2) { NSLog(@" %@", aStr); }
ブロック記法を用いたソート
NSArray *anArray = @[@"098", @"245", @"678"]; NSArray *sortedArray = [anArray sortedArrayUsingComparator: ^(NSString *leftStr, NSString *rightStr) { NSUInteger leftLength = leftStr.length; NSUInteger rightLength = rightStr.length;
if (leftLength > rightLength) { return NSOrderedDescending; } else if (leftLength < rightLength ) { return NSOrderedAscending; } else {
for (int i = 0 ; i <= leftLength ; i++ ) { unichar leftChar = [leftStr characterAtIndex:i]; unichar rightChar = [rightStr characterAtIndex:i];
if (leftChar > rightChar ) { return NSOrderedDescending; } else if ( leftChar < rightChar ) { return NSOrderedAscending; } } }
return NSOrderedSame; } ];
NSLog(@"sorted by block Comparator:"); for (NSString *aStr in sortedArray) { NSLog(@" %@", aStr); }
要素へメッセージの送信
すべてへ一斉送信
[anArray makeObjectsPerformSelector:@selector(description)];
引数を与えて
@interface NSMutableString (categoryExtensions) - (void) addStringAtTail:(NSString *) aTailString; @end
@implementation NSMutableString (categoryExtensions)
- (void) addStringAtTail:(NSString *) aTailString { [self appendString:aTailString]; }
// 同じく、NSArrayのメソッド追加 //NSStringの要素を持つ配列をNSLog()へ放り込むと、文字化け。 //ちゃんと文字が出力されるように、メソッドをカテゴリで追加。 @interface NSArray (categoryExtensions) - (void)myPrintComponents; @end
@implementation NSArray (categoryExtensions)
- (void)myPrintComponents { NSArray *anArray = self; for (id anObj in anArray) { NSLog(@" %@", [anObj description]); } }
@end
//配列の初期化 NSArray *anArray = @[ [NSMutableString stringWithString:@"air"], [NSMutableString stringWithString:@"123"], [NSMutableString stringWithString:@"あいう"], [NSMutableString stringWithString:@"幸せ"], [NSMutableString stringWithString:@"*&^"] ];
NSString *ext = @".jpg"; [anArray makeObjectsPerformSelector:@selector(addStringAtTail:) withObject:ext]; [anArray myPrintComponents];
ブロックを用いて、全ての要素へアクセス
[anArray enumerateObjectsUsingBlock: ^(NSString *str, NSUInteger index, BOOL *stop) { NSLog(@"str: %@ (%lu)", str, (unsigned long)index); if (str.length >= 3) { *stop = YES; } // if ends } // block ends ]; // message ends
ファイル入出力
プロパティ形式で書き出し
BOOL isSuccess; isSuccess = [anArray writeToFile:filePathString atomically:YES]; NSLog(@"write to file: %@", isSuccess ? @"Yes, successful!" : @"No, failure...");
プロパティ形式で保存されたファイルから初期化。
NSArray *anArrayFromPlist = [NSArray arrayWithContentsOfFile:filePathString];
結合して、文字列を生成
NSString *aSeparator = @"/"; NSString *aJoinedString = [anArray componentsJoinedByString:aSeparator]; NSString *aJoinedHeadingSlash = [@[@"/", anArray] componentsJoinedByString:anSeparator]; // これをするなら、NSURLを使おう。
指定する拡張子を持つNSStringの要素を抽出
// 引数の文字列配列は、拡張子群を表す。 // 格納要素で、マッチする拡張子を持つモノを一時変数へ格納して返す。 NSArray *extensions = @[@"jpg", @"png", @"tiff"]; NSArray *files = @[@"a.word", @"b.tiff", @"c.xls", @"d.png", @"e.txt", ]; NSLog(@"with the extensions: %@", [files pathsMatchingExtensions:extensions] );
NSMutableArray
初期化
NSMutableArray *aMutableArray1 = [NSMutableArray arrayWithCapacity:10]; NSMutableArray *aMutableArray2 = [NSMutableArray array]; // 空の配列
[ aMutableArray1 setArray:@[@"6.plist", @"使えない.word", @"1.tiff", @"2.xls", ]];
NSMutableArray *aMutalbeArray3 = @[@"234", @"34567"].mutableCopy;
追加、置換、削除
追加
[aMutableArray addObject:@"末尾へ追加"]; [aMutableArray addObjectsFromArray: otherArray]; [aMutableArray insertObject:@"挿入" atIndex:2]; // インデックスは、0から始まる。
置換
[aMutableArray replaceObjectAtIndex:2 withObject:@"置換した要素"];
// replaceWithRange 範囲の要素を削除して、代わりに引数の配列で置き換える。 NSArray *aReplacements = @[@"部分", @"置換"]; NSRange aRange = NSMakeRange(0, aReplacement.count); [aMutableArray replaceObjectsInRange:aRange withObjectsFromArray:aReplacements];
// 丸ごと置換 [aMutableArray setArray:otherArray];
//要素の交換 [aMutableArray exchangeObjectAtIndex:5 withObjectAtIndex:2];
削除
//末尾の要素を削除 [aMutableArray removeLastObject];
//引数インデックスにある要素を削除 [aMutableArray removeObjectAtIndex:2];
//NSRange を使用して、範囲にある要素を削除 NSRange aRange = NSMakeRange(2, 2); [aMutableArray removeObjectsInRange:aRange];
//引数オブジェクトと同じ要素を全て削除 // 等しいとは、isEqualTo で比較して、YESを返すもの。 // アドレスが同じなら等しい。 [aMutableArray removeObject:@"6.plist"];
//引数配列の中にある要素1つと一致で、削除 [aMutableArray removeObjectsInArray:@[@"1.tiff", @"4.txt"]];
NSMutableArrayの要素を調べて、条件が成り立つ要素を削除
ループで実装。要素を最後から調べること、でないと循環してしまう。 NSInteger len, idx; len = aMutableArray.count; BOOL check1 = NO;
for (idx = len - 1 ; idx >= 0 ; idx-- ) { NSString *aStr = [aMutableArray objectAtIndex:idx]; check1 = [aStr doesContainNumber];
if ( check1 ) { [aMutableArray removeObjectAtIndex:idx]; } }
ソート。NSArray と違い、自分が持つ要素をソートする。
セレクタを用いたソート
[aMutableArray sortUsingSelector:@selector(compare:)];
カテゴリで追加した、自前のソートセレクタでソート
//NSString をソートする簡単なメソッドをカテゴリで追加 @interface NSString (categoryExtension) - (NSComparisonResult) myCompare:(NSString *) counterString; - (BOOL) doesContainNumber; @end
@implementation NSString (categoryExtension)
- (NSComparisonResult) myCompare:(NSString *)counterString { NSString *leftString = self; NSString *rightString = counterString;
NSUInteger lengthOfLeftString = leftString.length; NSUInteger lengthOfRightString = rightString.length;
if ( lengthOfLeftString < lengthOfRightString) { return NSOrderedAscending;
} else if ( lengthOfLeftString > lengthOfRightString ) { return NSOrderedDescending;
} else { // same length // compare each character step by step for (int i = 0 ; i <= lengthOfRightString; i++ ) { unichar leftChar = [leftString characterAtIndex:i]; unichar rightChar = [rightString characterAtIndex:i];
if (leftChar < rightChar ) { return NSOrderedAscending; } else if ( leftChar > rightChar ) { return NSOrderedDescending; } // if ends
} // for ends } // if ends
return NSOrderedSame; }
@end
[aMutableArray sortUsingSelector:@selector(myCompare:)];
ブロックを用いたソート
[aMutableArray sortUsingComparator :^(NSString *leftStr, NSString *rightStr) { NSUInteger leftLength = leftStr.length; NSUInteger rightLength = rightStr.length;
if (leftLength < rightLength) { return NSOrderedDescending; } else if (leftLength > rightLength ) { return NSOrderedAscending; } else {
for (int i = 0 ; i <= leftLength ; i++ ) { unichar leftChar = [leftStr characterAtIndex:i]; unichar rightChar = [rightStr characterAtIndex:i];
if (leftChar < rightChar ) { return NSOrderedDescending; } else if ( leftChar > rightChar ) { return NSOrderedAscending; } } }
return NSOrderedSame; } ];
関数を用いたソート
//美しくない。色んなところで利用するなら、あり。 // 関数ポインターの定義 NSComparisonResult (*pointerFunction)(__strong id, __strong id, void *); pointerFunction = compareFunction; void *aContext = NULL; // 関数への第三引数、任意。これを使って比較動作を細かく設定できる、 [aMutableArray sortUsingFunction:pointerFunction context:aContext];
列挙
高速列挙
for (id anObject in anArray) { NSLog(@"%@", [anObject description]); }
逆順の高速列挙
for ( id anObject in [aArray reverseObjectEnumerator] ) { NSLog(@"%@", [anObject description]); }
列挙子を使う
id anObject; NSEnumerator *anEnumerator;
anEnumerator = [aArray objectEnumerator]; while ( (anObject = [anEnumerator nextObject]) != nil) { NSLog(@"enumerator: %@", [anObject description] ); }
列挙子の逆順
anEnumerator = [anArray reverseObjectEnumerator]; for (anObject in anEnumerator ) { /* 省略 */ }