【Objective-C】NSMutableArrayの使い方15選!初心者でも簡単

Objective-CでNSMutableArrayを使ってデータ管理をマスターする初心者向けガイドObjctive-C
この記事は約35分で読めます。

※Japanシーモアは、利用目的を問わず掲載されているコードの再利用が可能です。常に解説内容のわかりやすさや記事の品質に注力しておりますので、不具合・分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。(理解できない部分などの個別相談も無償で承っております)
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

Objective-Cを学ぶ上で、NSMutableArrayは避けて通れない存在です。

この記事では、NSMutableArrayの基本から、そのカスタマイズ方法までを、15の異なる使い方をサンプルコードと共に紹介します。

初心者でも理解しやすいよう、基礎知識の確認から応用テクニックまで、実用的な例を用いて詳しく解説します。

それでは、NSMutableArrayの多様な機能を一緒に見ていきましょう。

●Objective-Cとは?

Objective-Cは、C言語にオブジェクト指向の機能を加えたプログラミング言語です。

AppleによるmacOSやiOSのアプリケーション開発に長年使われてきました。

シンプルなC言語の構文に加え、Smalltalk言語の影響を受けたメッセージ指向の構文が特徴です。

Objective-CはC言語のサブセットであるため、C言語のコードをそのまま利用できる点も大きな利点の一つです。

○Objective-Cの歴史

Objective-Cは1980年代初頭にBrad CoxとTom Loveによって開発されました。

NeXT Computerによって商業化された後、AppleによるNeXTの買収と共にMac OS Xの主要な開発言語となり、iOSの登場でさらに普及しました。

しかし、2014年にAppleがSwiftを発表して以来、Swiftに徐々にその地位を譲っています。

とはいえ、既存の多くのMacやiOSアプリケーションはObjective-Cで書かれているため、現在もObjective-Cの知識は価値があります。

○Objective-Cの特徴

Objective-Cの大きな特徴は、動的な言語機能を持っている点です。

クラスやメソッドの定義を実行時に変更することができ、柔軟なプログラミングが可能となります。

また、Objective-Cはポインタやマニュアルメモリ管理など、C言語の低レベルの制御機能を直接使用できるため、効率的なプログラムを書くことができます。

一方で、記述が複雑になるという欠点もありますが、アップルが提供する豊富なフレームワークと組み合わせることで、強力なアプリケーションを作成できます。

●NSMutableArrayとは?

NSMutableArrayはObjective-Cにおける動的配列の一種で、そのサイズや要素を実行時に変更できる配列です。

NSArrayクラスのサブクラスであり、NSArrayが持つ全ての特性に加えて、要素の追加や削除が可能です。

この柔軟性は、配列に格納する要素の数が事前に定かでない場合や、プログラム実行中に要素の数が変わる可能性がある時に特に有効です。

Objective-CでのコレクションとしてNSMutableArrayは重要な役割を果たし、多くのiOSやmacOSのアプリケーションで広く利用されています。

例えば、ユーザーがアプリケーションに入力したデータの一覧や、変更可能な設定の集合を管理する場合などに使われます。

NSMutableArrayを使うことで、配列内のオブジェクトを簡単にソートしたり、特定の条件に基づいてフィルタリングするといった操作も容易に行えます。

○配列とは何か?

配列とは複数の値を一定の順序で格納するコンテナのことを指します。

Objective-Cにおいて、NSArrayは不変の配列を表し、一度作成するとその内容を変更できません。

一方でNSMutableArrayは、内容の変更が可能な配列で、動的に要素を管理する際に有用です。

配列は変数の集合体として機能し、単一の変数名で多数のデータを扱うことができるため、プログラムの複雑性を減少させ、データ構造を単純化します。

例えば、ユーザーのリストや商品のカタログなど、同種のデータを一つのグループとして管理する際に使用されます。

各要素はインデックスを使ってアクセスされ、通常は0から始まる連番が割り当てられます。

○NSMutableArrayの基本

NSMutableArrayの基本的な使い方には、新しい配列の作成、要素の追加と削除、要素の検索、配列のコピーといった操作が含まれます。

NSMutableArrayは多くのメソッドを提供しており、これらのメソッドを利用することで、配列の操作を容易に行うことができます。

また、NSMutableArrayはオブジェクトの参照を保持するため、基本的なデータ型は直接格納することができず、NSNumberやNSStringなどのオブジェクトを介して格納する必要があります。

これにより、数値や文字列だけでなく、カスタムオブジェクトも格納可能になり、非常に強力なデータ構造を作成することができます。

●NSMutableArrayの作成方法

NSMutableArrayはObjective-Cで配列データを動的に管理するためのクラスです。

配列とは複数のデータを一定の順序で格納するデータ構造で、Objective-CにおいてはNSArrayのサブクラスとしてNSMutableArrayが提供されています。

NSArrayクラスはイミュータブル(変更不可能)な配列を、NSMutableArrayクラスはミュータブル(変更可能)な配列をそれぞれ扱います。

NSMutableArrayを使用すると、配列に含まれるオブジェクトの追加、削除、置換が可能となり、柔軟なデータ管理が行えます。

このクラスを使用するためには、対象となるNSMutableArrayオブジェクトを作成する必要があります。

これは次の二つの方法で実施可能です。

  1. 空のNSMutableArrayを作成する。
  2. 既存のオブジェクトからNSMutableArrayを作成する。

これらのメソッドは状況に応じて選択することができ、Objective-Cプログラミングにおいて非常に頻繁に利用されます。

○サンプルコード1:空のNSMutableArrayを作成

Objective-CでNSMutableArrayのインスタンスを生成する基本的な方法を紹介します。

このサンプルコードでは、空のNSMutableArrayオブジェクトを作成しています。

// NSMutableArrayの新しいインスタンスを作成
NSMutableArray *mutableArray = [[NSMutableArray alloc] init];

このコードでは、NSMutableArrayクラスのallocメソッドを呼び出して新しいインスタンスをメモリに確保し、initメソッドでそのインスタンスを初期化しています。

この結果、要素を含まない空の配列が作成されます。

○サンプルコード2:オブジェクトで初期化したNSMutableArrayを作成

NSMutableArrayは既存のNSArrayオブジェクトや他のNSMutableArrayオブジェクトからも作成することができます。

例えば、下記のコードではNSArrayに格納されているオブジェクトを使ってNSMutableArrayインスタンスを初期化しています。

// 既存のNSArrayからNSMutableArrayを作成
NSArray *array = @[@"Apple", @"Banana", @"Cherry"];
NSMutableArray *mutableArrayFromExistingArray = [NSMutableArray arrayWithArray:array];

この例では、リテラル記法を使用してNSArrayのインスタンスarrayを作成し、それをNSMutableArrayarrayWithArray:メソッドに渡しています。

このメソッドはNSArrayの内容を新しいNSMutableArrayにコピーして、変更可能な配列を作ります。

●NSMutableArrayへの要素の追加方法

Objective-CにおけるNSMutableArrayは、その名の通り、変更可能な配列を扱うためのクラスです。

これを使うことで、配列に対する動的な要素の追加や削除が可能になります。

特に要素の追加に関しては、アプリケーションの実行中にユーザーのアクションや外部からのデータ入力に応じて配列の内容を柔軟に変更することができます。

NSMutableArrayへの要素の追加は、主にaddObject:メソッドやinsertObject:atIndex:メソッドを使用します。

addObject:メソッドは配列の末尾に新しい要素を追加するのに対し、insertObject:atIndex:メソッドでは特定の位置に要素を挿入できるという特徴があります。

これらのメソッドはNSMutableArrayが提供する機能の基本であり、効率的なデータ管理を実現する上で不可欠です。

○サンプルコード3:単一のオブジェクトを追加

Objective-CでNSMutableArrayに単一のオブジェクトを追加する方法は非常にシンプルです。

下記のサンプルコードは、新しい文字列オブジェクトをNSMutableArrayに追加するプロセスを表しています。

// NSMutableArrayを作成します
NSMutableArray *mutableArray = [NSMutableArray array];

// 文字列オブジェクトを追加します
[mutableArray addObject:@"Apple"];

// 配列の内容をコンソールに出力します
NSLog(@"%@", mutableArray);

このコードではまず、NSMutableArrayのインスタンスを生成し、空の配列を作成しています。

次にaddObject:メソッドを使用して@"Apple"という文字列オブジェクトを追加しています。

そしてNSLog関数を使って配列の内容をコンソールに出力しています。

この例では配列に@"Apple"という文字が追加された状態で表示されます。

○サンプルコード4:複数のオブジェクトを追加

NSMutableArrayに複数の要素を効率的に追加するには、複数のオブジェクトを含む配列を用意し、addObjectsFromArray:メソッドを利用することができます。

下記のサンプルでは、複数の文字列オブジェクトを含む配列をNSMutableArrayに追加する手順を説明しています。

// NSMutableArrayを作成します
NSMutableArray *mutableArray = [NSMutableArray array];

// 追加する文字列オブジェクトの配列を作成します
NSArray *additionalStrings = @[@"Banana", @"Cherry", @"Date"];

// 配列に複数のオブジェクトを追加します
[mutableArray addObjectsFromArray:additionalStrings];

// 配列の内容をコンソールに出力します
NSLog(@"%@", mutableArray);

ここでNSMutableArrayに対してaddObjectsFromArray:メソッドを使用することで、@"Banana", @"Cherry", @"Date"という3つのオブジェクトが既存の配列に一度に追加されていることがわかります。

ログ出力の結果として、これらの要素が配列に含まれることが表されます。

○サンプルコード5:特定の位置にオブジェクトを挿入

配列の特定の位置に要素を挿入する場合、insertObject:atIndex:メソッドが用いられます。

このメソッドを使うと、指定したインデックスの位置に新たなオブジェクトを挿入することができます。

下記のサンプルでは、第二の位置に新しい要素を追加する方法を説明します。

// NSMutableArrayを作成します
NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"Apple", @"Banana", nil];

// インデックス1の位置に新しいオブジェクトを挿入します。これは二番目の位置です
[mutableArray insertObject:@"Cherry" atIndex:1];

// 配列の内容をコンソールに出力します
NSLog(@"%@", mutableArray);

このコードでは@"Cherry"という新しいオブジェクトを既存の@"Apple"@"Banana"の間、すなわちインデックス1の位置に挿入しています。

実行結果としてコンソールには@"Apple", @"Cherry", @"Banana"の順でオブジェクトが並んでいることが表示されるでしょう。

これにより、配列の任意の位置への挿入が如何に簡単かが理解できます。

●NSMutableArrayからの要素の削除方法

NSMutableArrayはObjective-Cで動的配列を扱う際に使用されるクラスです。

動的配列とは、要素の数が実行時に変更可能な配列のことで、要素の追加や削除が可能です。

NSMutableArrayからの要素の削除は、多くのアプリケーションで基本的な操作となります。

要素を削除する方法は、特定のオブジェクトを指定して削除する方法、特定のインデックスのオブジェクトを削除する方法、配列内の全てのオブジェクトを削除する方法などがあります。

これらの操作を正しく行うことで、アプリケーションのデータ管理が効率的に行われます。

○サンプルコード6:特定のオブジェクトを削除

NSMutableArrayには、特定のオブジェクトを削除するためのメソッドremoveObject:が用意されています。

下記のコードは、NSStringオブジェクトの@"example"が配列に存在する場合、そのオブジェクトを削除する方法を表しています。

NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"example", @"demo", @"sample", nil];
[array removeObject:@"example"]; // @"example"という文字列オブジェクトを削除します。

このコードではNSMutableArrayに初期値として3つの文字列を追加した後、@"example"という文字列を削除しています。

削除操作後、配列には@"demo"@"sample"のみが残ります。

○サンプルコード7:特定の位置のオブジェクトを削除

配列の特定の位置にあるオブジェクトを削除するには、removeObjectAtIndex:メソッドを使用します。

例えば、下記のコードでは配列の0番目の要素を削除しています。

NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"example", @"demo", @"sample", nil];
[array removeObjectAtIndex:0]; // インデックス0の要素を削除します。

この操作を行うと、@"example"が配列から削除され、新たな0番目の要素として@"demo"が位置することになります。

○サンプルコード8:全てのオブジェクトを削除

全ての要素をNSMutableArrayから削除するには、removeAllObjectsメソッドを利用します。

これにより、配列内の全てのオブジェクトが削除されます。

NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"example", @"demo", @"sample", nil];
[array removeAllObjects]; // 配列の全要素を削除します。

このコードを実行すると、arrayは空の状態になります。

これらの削除メソッドを使用する際には、配列が空でないこと、または削除しようとするインデックスが配列の範囲内であることを確認することが重要です。

誤ったインデックスに対して削除を試みると、プログラムがクラッシュする可能性があるため、プログラムの安全性を確保するためにはこれらの点に注意が必要です。

また、オブジェクトの削除はメモリ管理にも関わる操作であり、特に古いObjective-Cのコードではretainとreleaseを適切に行うことが重要です。

しかし、ARC(Automatic Reference Counting)を使用する現代のコードでは、このようなメモリ管理は自動化されています。

●NSMutableArrayの要素へのアクセス方法

NSMutableArrayはObjective-Cにおいて、変更可能な配列を扱うためのクラスです。

配列の要素へのアクセスは、効率的なデータ管理と操作に不可欠です。

要素へのアクセスは主にインデックスを使用し、指定した位置の要素を取得することができます。

要素にアクセスする際、存在しないインデックスを指定するとプログラムがクラッシュする可能性があるため、アクセスする前に配列のサイズを確認するか、例外を防ぐための適切なコーディングが求められます。

配列の要素を安全に扱うためには、NSMutableArrayに用意されているメソッドを適切に使用することが重要です。

また、NSMutableArrayには他にも、要素の追加、削除、挿入といった操作を行うメソッドが用意されており、これらのメソッドを使いこなすことで柔軟な配列操作が可能になります。

○サンプルコード9:インデックスを指定して要素を取得

Objective-CでNSMutableArrayの特定の位置にある要素を取得するためには、objectAtIndex: メソッドを使用します。

このメソッドは、指定したインデックスのオブジェクトを返します。

// NSMutableArrayの初期化とオブジェクトの追加
NSMutableArray *myArray = [[NSMutableArray alloc] initWithObjects:@"Apple", @"Banana", @"Cherry", nil];

// インデックス0の要素を取得
NSString *firstElement = [myArray objectAtIndex:0];

// 取得した要素の表示
NSLog(@"最初の要素: %@", firstElement);

このコードでは、myArray というNSMutableArrayを初期化し、「Apple」、「Banana」、「Cherry」という3つの文字列を追加しています。

その後、objectAtIndex: メソッドを用いてインデックス0の要素「Apple」を取得し、ログに表示しています。

実行すると、次のような出力が得られます。

最初の要素: Apple

○サンプルコード10:最後の要素を取得

NSMutableArrayの最後の要素にアクセスするには、lastObject プロパティを使用します。

これは、配列の最後のオブジェクトを返すか、配列が空の場合はnilを返します。

// NSMutableArrayの初期化とオブジェクトの追加
NSMutableArray *myArray = [[NSMutableArray alloc] initWithObjects:@"Apple", @"Banana", @"Cherry", nil];

// 配列の最後の要素を取得
NSString *lastElement = [myArray lastObject];

// 取得した要素の表示
NSLog(@"最後の要素: %@", lastElement);

このコードを実行すると、NSMutableArrayの最後に追加された「Cherry」が取得され、次のように表示されます。

最後の要素: Cherry

○サンプルコード11:配列をループして要素にアクセス

NSMutableArrayの全要素に順番にアクセスする一般的な方法は、for ループを使用することです。

for ループを使うと、配列の最初から最後までの要素を繰り返し処理することができます。

// NSMutableArrayの初期化とオブジェクトの追加
NSMutableArray *myArray = [[NSMutableArray alloc] initWithObjects:@"Apple", @"Banana", @"Cherry", nil];

// forループを使用して全要素にアクセス
for (int i = 0; i < [myArray count]; i++) {
    NSString *element = [myArray objectAtIndex:i];
    NSLog(@"要素 %d: %@", i, element);
}

このコードでは、count メソッドを使って配列のサイズを取得し、0からサイズ未満のインデックスまでループを回して各要素にアクセスしています。

各要素は、インデックスと共にログに表示されます。

実行すると、次の出力を得ます。

要素 0: Apple
要素 1: Banana
要素 2: Cherry

●NSMutableArrayの編集方法

NSMutableArrayはObjective-Cで使われる動的な配列です。

通常のNSArrayと異なり、NSMutableArrayは要素の追加や削除、置換が可能であり、iOS開発やMac開発において非常に役立つクラスの一つです。

NSMutableArrayを効率的に編集するためには、メソッドの適切な使用が必要です。

ここでは、NSMutableArrayの編集方法を細かく説明し、具体的なコード例を交えて解説します。

○サンプルコード12:特定のインデックスの要素を置換

Objective-Cでは、NSMutableArrayの特定のインデックスにあるオブジェクトを新しいオブジェクトで置換する操作が一般的です。

下記のコードは、インデックスが2の位置にあるオブジェクトを新しいオブジェクト「@”新しい要素”」で置換する一連の流れを表しています。

// NSMutableArrayのインスタンスを生成
NSMutableArray *array = [NSMutableArray arrayWithObjects:@"要素1", @"要素2", @"要素3", nil];

// インデックス2の要素を新しい要素で置換
[array replaceObjectAtIndex:2 withObject:@"新しい要素"];

// 置換後の配列をログに出力
NSLog(@"更新された配列: %@", array);

このコードでは、「NSMutableArray」を使って初期に3つのオブジェクトを持つ配列を作成し、その後で「replaceObjectAtIndex:withObject:」メソッドを使用してインデックス2の要素(「要素3」)を「新しい要素」という文字列で置換しています。

この操作を行うと、配列は「要素1」、「要素2」、「新しい要素」という新しい構成になります。ログに出力することで確認が可能です。

配列の編集はデータ構造の変更に直結するため、その影響を理解した上で慎重に行う必要があります。このシンプルな例を基にして、条件に応じた編集方法を覚えることが重要です。

編集後の配列の内容をログ出力した結果、コンソールには「更新された配列: (要素1, 要素2, 新しい要素)」と表示されるでしょう。

この出力結果から、特定の位置の要素が期待通りに新しいオブジェクトに置換されたことが確認できます。

○サンプルコード13:条件に合う要素だけを置換

複数の要素を条件に応じて置換する必要がある場合は、下記のようなコードを書くことができます。

// NSMutableArrayのインスタンスを生成
NSMutableArray *array = [NSMutableArray arrayWithObjects:@"apple", @"banana", @"cherry", @"date", nil];

// "a"で始まる要素だけを「"ananas"」で置換する
for (NSInteger i = 0; i < [array count]; i++) {
    if ([array[i] hasPrefix:@"a"]) {
        [array replaceObjectAtIndex:i withObject:@"ananas"];
    }
}

// 置換後の配列をログに出力
NSLog(@"条件に合う要素を置換した配列: %@", array);

ここでは、forループと「hasPrefix:」メソッドを用いて、「a」で始まる文字列を持つ要素を「”ananas”」で置換しています。

結果として「apple」と「ananas」が「ananas」に置換され、配列の他の要素は変更されません。

ログに出力すると、「条件に合う要素を置換した配列: (ananas, banana, cherry, date)」という結果が得られ、条件に基づいた編集が適切に行われていることを確認できます。

●NSMutableArrayの並べ替え方法

NSMutableArrayの並べ替えは、Objective-Cにおける強力な機能の一つです。

配列内の要素を並べ替えることは、多くのアプリケーションで基本的な要件となります。

例えば、ユーザーの入力に基づいたリストのソートや、データのアルファベット順での表示など、状況に応じてさまざまな並べ替えが求められることがあります。

Objective-CではNSMutableArrayに対して、簡単に並べ替えを実行する方法がいくつか提供されています。

○サンプルコード14:単純な並べ替え

ここでは、比較可能なオブジェクトを含むNSMutableArrayの要素を並べ替えるための基本的なメソッドsortUsingComparator:の使用方法を見ていきます。

このメソッドを使用することで、ブロック内で定義した比較ロジックに基づいて要素の順序を並び替えることができます。

// NSMutableArrayのインスタンスを作成し、数値を追加
NSMutableArray *numbers = [NSMutableArray arrayWithObjects:@(3), @(1), @(4), @(1), @(5), @(9), @(2), @(6), @(5), @(3), nil];

// 数値を昇順に並べ替え
[numbers sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    return [obj1 compare:obj2];
}];

// 結果をログに出力
NSLog(@"Sorted Numbers: %@", numbers);

このコードではNSMutableArrayに数値オブジェクトを追加してから、sortUsingComparator:メソッドを用いています。

この例では数値を昇順で並び替えており、obj1obj2compare:メソッドを使って比較しています。

比較ブロックはNSComparisonResultを返し、配列の各要素が比較され、ソートされた結果がnumbers配列に格納されます。ログに出力すると、昇順に並べ替えられた数値のリストが得られます。

このコードを実行すると、次のような出力が得られるでしょう。

Sorted Numbers: (1, 1, 2, 3, 3, 4, 5, 5, 6, 9)

この出力結果から、配列の要素が正しく昇順に並べ替えられたことがわかります。

○サンプルコード15:カスタム比較を使った並べ替え

NSMutableArrayの要素を並べ替える際には、特定の条件に基づいたカスタムの比較も可能です。

下記のサンプルコードでは、文字列の長さで配列を並べ替える方法を表しています。

// 文字列のNSMutableArrayインスタンスを作成
NSMutableArray *strings = [NSMutableArray arrayWithObjects:@"banana", @"apple", @"cherry", @"date", nil];

// 文字列をその長さに基づいて昇順に並べ替え
[strings sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    // 文字列の長さを比較する
    NSUInteger len1 = [obj1 length];
    NSUInteger len2 = [obj2 length];
    if (len1 > len2) {
        return NSOrderedDescending;
    } else if (len1 < len2) {
        return NSOrderedAscending;
    } else {
        return NSOrderedSame;
    }
}];

// 結果をログに出力
NSLog(@"Sorted Strings by length: %@", strings);

このコードでは、NSMutableArrayに含まれる文字列オブジェクトの長さを基準にしてソートしています。

sortUsingComparator:メソッド内でブロックを定義し、obj1obj2の長さを取得後、長さを比較しています。

結果として得られるのは、文字列の長さ順にソートされた配列です。

実行結果をログに出力すると、文字列が長さに応じて並び替えられていることが確認できます。

実行後の出力は次のようになります。

Sorted Strings by length: (date, apple, banana, cherry)

この結果から、dateから始まりcherryで終わるまで、文字列が正しく長さに基づいて昇順に並べ替えられたことを確認できます。

この方法を使用すると、複雑な条件やカスタムのデータ型に対しても柔軟に並べ替えを行うことができます。

●NSMutableArrayを使った応用例

NSMutableArrayはObjective-Cで配列を柔軟に操作するための強力なツールです。

このクラスを使って開発の幅を広げるためには、基本的な機能を超えた応用が不可欠です。

ここでは、実際のアプリケーションでよく使われる、幾つかの応用例について紹介します。

○サンプルコード16:NSMutableArrayを使ったToDoリスト

ToDoリストはアプリケーション開発で最も一般的な例の一つです。

NSMutableArrayを使ってToDoアイテムのリストを管理する例を見てみましょう。

// ToDoリストのアイテムを保持するためのNSMutableArrayを定義します。
NSMutableArray *toDoList = [[NSMutableArray alloc] init];

// ToDoアイテムをNSMutableArrayに追加する方法です。
[toDoList addObject:@"牛乳を買う"];
[toDoList addObject:@"レポートを書く"];
[toDoList addObject:@"犬の散歩をする"];

// NSMutableArrayに追加したToDoアイテムを表示します。
for (NSString *toDoItem in toDoList) {
    NSLog(@"%@", toDoItem);
}

このコードではNSMutableArrayを使って文字列のオブジェクトを保存することでToDoリストを作成しています。for-inループを使用して配列内の全てのアイテムをログに出力しています。

実際にアプリケーションを実行すると、次のような出力が得られます。

これは配列に追加した順序で各ToDoアイテムがコンソールに表示されることを意味します。

牛乳を買う
レポートを書く
犬の散歩をする

○サンプルコード17:NSMutableArrayを用いたデータのフィルタリング

アプリケーションにおけるデータ処理では、特定の条件に基づいて配列内のオブジェクトをフィルタリングすることがよくあります。

下記の例は、NSMutableArrayから特定の条件を満たすオブジェクトだけを見つける方法を表しています。

// データセットのNSMutableArrayを定義します。
NSMutableArray *numbers = [@[@(23), @(45), @(66), @(88), @(12), @(15)] mutableCopy];

// フィルタ条件を設定します。ここでは"20より大きい数"とします。
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self > 20"];

// フィルタリングされた配列を取得します。
NSArray *filteredNumbers = [numbers filteredArrayUsingPredicate:predicate];

// 結果を表示します。
NSLog(@"Filtered Numbers: %@", filteredNumbers);

このコードでは、NSPredicateを使用してフィルタリングを行い、20より大きい数値のみを含む新しい配列を生成しています。

実行結果として、元の配列numbersから条件を満たすオブジェクトだけが選択されます。

コンソールには次のような結果が出力されます。

Filtered Numbers: (23, 45, 66, 88)

○サンプルコード18:NSMutableArrayの内容をファイルに保存

データの永続化は、多くのアプリケーションで重要な部分です。

配列の内容をファイルに保存して後で読み込むことは、データ永続化の基本的な方法の一つです。

// データのNSMutableArrayを定義します。
NSMutableArray *colors = [NSMutableArray arrayWithObjects:@"赤", @"緑", @"青", nil];

// ドキュメントディレクトリのパスを取得します。
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];

// 保存するファイルのパスを設定します。
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"colors.plist"];

// NSMutableArrayの内容をファイルに保存します。
[colors writeToFile:filePath atomically:YES];

// ファイルからNSMutableArrayの内容を読み込みます。
NSMutableArray *savedColors = [[NSMutableArray alloc] initWithContentsOfFile:filePath];

// 結果を表示します。
NSLog(@"Saved Colors: %@", savedColors);

このコードではwriteToFile:atomically:メソッドを使用して配列colorsをプロパティリスト(.plist)ファイルとして保存しています。

保存したデータは、後でinitWithContentsOfFile:メソッドによって新しいNSMutableArrayとして読み込まれます。

保存後、読み込んだ配列を出力すると、次のように元の配列と同じ内容のデータが表示されます。

Saved Colors: (赤, 緑, 青)

●NSMutableArrayの注意点と対処法

Objective-CにおけるNSMutableArrayは、可変長配列を扱う上で非常に便利なクラスですが、その柔軟性ゆえにいくつかの注意点が存在します。

特に、プログラムの安定性やパフォーマンスを維持するためには、正しいメモリ管理とスレッドセーフの操作が求められます。

○メモリ管理の基本

Objective-Cのメモリ管理では、参照カウントという形でオブジェクトのライフサイクルを管理しています。

NSMutableArrayを含むすべてのオブジェクトは、alloc、copy、mutableCopyなどの操作で生成された際には、参照カウントが1となります。

オブジェクトを配列などに保持する際は、その配列もオブジェクトの参照カウントを増やすため、オブジェクトは適切なタイミングでreleaseまたはautoreleaseを呼び出して参照カウントを減らす必要があります。

NSMutableArrayの要素が不要になった場合は、明示的に要素を削除することで参照カウントを下げ、メモリリークを防ぐことができます。

また、ARC(Automatic Reference Counting)を使用している場合は、これらの操作がコンパイラによって自動的に行われるため、開発者はARCの規則を理解し、適切なコーディングを行う必要があります。

○NSMutableArrayを安全に使うためのTips

□スレッドセーフの保証がないことに注意する

NSMutableArrayはスレッドセーフではないため、複数のスレッドから同時にアクセスすることは避けるべきです。

複数のスレッドが同一のNSMutableArrayに対して操作を行う場合には、@synchronizedブロックを使用してアクセスを制御することが推奨されます。

□メモリ溢れを防ぐために適切なサイズで初期化する

配列が巨大になり得る場合は、適切なcapacityを指定して初期化することで、再割り当ての回数を減し、パフォーマンスを向上させることができます。

□要素の追加と削除を効率的に行う

addObject:やremoveObjectAtIndex:メソッドを使用することで、配列の管理を効率的に行えますが、大量の要素の追加や削除を一度に行う際は、beginUpdatesとendUpdatesメソッドを使用して、処理の最適化を図ることができます。

これらのTipsを踏まえた上で、NSMutableArrayを使用する際のコード例をで紹介します。

// NSMutableArrayの安全な使用例
NSMutableArray *exampleArray = [[NSMutableArray alloc] initWithCapacity:10]; // 適切なcapacityで初期化
// 複数スレッドからのアクセスが予想される場合
@synchronized(exampleArray) {
    [exampleArray addObject:@"Example Object"];
    // 他のスレッドセーフでない操作...
}

このコードでは、10要素の容量を持つNSMutableArrayを初期化しています。

@synchronized ブロックを使用することで、スレッドセーフではないNSMutableArrayへのアクセスをスレッド間で排他制御しています。

●カスタマイズ方法

NSMutableArrayはObjective-Cで動的な配列を扱うためのクラスです。

NSArrayのサブクラスであるNSMutableArrayは、要素の追加や削除が自由に行え、配列のサイズが動的に変更されます。

カスタマイズ可能なこの配列を使いこなすことで、Objective-Cの開発においてより柔軟かつ強力なデータ構造を実装できます。

○カテゴリを使ったNSMutableArrayの拡張

カテゴリ(category)はObjective-Cの強力な機能の一つで、既存のクラスにメソッドを追加することができます。

NSMutableArrayに独自の機能を追加したい場合、カテゴリを定義してメソッドを追加することが一般的です。

例えば、配列の要素を特定の規則に基づいてフィルタリングするカスタムメソッドを追加することができます。

// NSMutableArray+Filtering.h
#import <Foundation/Foundation.h>

@interface NSMutableArray (Filtering)
- (void)removeObjectsMatchingPredicate:(NSPredicate *)predicate;
@end

// NSMutableArray+Filtering.m
#import "NSMutableArray+Filtering.h"

@implementation NSMutableArray (Filtering)

- (void)removeObjectsMatchingPredicate:(NSPredicate *)predicate {
    for (NSInteger i = [self count] - 1; i >= 0; i--) {
        if ([predicate evaluateWithObject:self[i]]) {
            [self removeObjectAtIndex:i];
        }
    }
}

@end

このコードではNSMutableArrayのカテゴリを定義しており、NSPredicateに基づいてオブジェクトを削除する新しいメソッド removeObjectsMatchingPredicate: を追加しています。

この例では指定された述語にマッチする全てのオブジェクトを配列から削除しています。

このメソッドを使うことで、例えば「数値が10未満のオブジェクトを全て削除する」という操作を簡単に行うことができます。

具体的な使用例は次の通りです。

NSMutableArray *array = [NSMutableArray arrayWithObjects:@1, @2, @15, @20, @25, nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self < 10"];
[array removeObjectsMatchingPredicate:predicate];

実行すると、arrayから1, 2が削除され、15, 20, 25のみが残ります。

○サブクラス化してNSMutableArrayをカスタマイズ

NSMutableArrayのサブクラスを作成することも、カスタマイズの一形態です。

サブクラスを作成すると、NSMutableArrayの基本的な機能に加えて、特定の操作をカスタマイズしたり、新たな機能を追加したりすることが可能になります。

例えば、配列にオブジェクトを追加する際にログを出力する機能を追加したサブクラスは次のようになります。

// LoggingArray.h
#import <Foundation/Foundation.h>

@interface LoggingArray : NSMutableArray
@end

// LoggingArray.m
#import "LoggingArray.h"

@implementation LoggingArray

- (void)addObject:(id)anObject {
    NSLog(@"Adding object: %@", anObject);
    [super addObject:anObject];
}

@end

このコードではLoggingArrayクラスはNSMutableArrayを継承しており、addObject:メソッドにログ出力機能を追加しています。

オブジェクトが追加される度にコンソールにその内容が出力されるため、デバッグ時に配列の状態を監視しやすくなります。

使用例としては、次のようになります。

LoggingArray *myArray = [[LoggingArray alloc] init];
[myArray addObject:@"First Item"];
[myArray addObject:@"Second Item"];

実行すると、各オブジェクトが追加される時にコンソールに追加されたオブジェクトの情報が表示されます。

まとめ

NSMutableArrayはObjective-Cで使用される動的な配列です。

これは静的な配列であるNSArrayと比較して、要素の追加や削除が柔軟に行えるため、プログラムの実行中にコレクションのサイズが変わる可能性がある場合に特に有効です。

この記事では、NSMutableArrayの様々な使い方を15の異なるシナリオを通して解説しました。

適切な使い方をマスターすれば、iOSやmacOSのアプリケーション開発において強力なツールとなります。

この記事があなたのObjective-Cにおける配列操作の理解を深める手助けになれば幸いです。