順序があり要素の重複は許さないコレクションクラス
解説
継承 | NSObject |
準拠 | NSCopying |
NSMutableCopying | |
NSFastEnumeration | |
NSSecureCoding | |
NSObject (NSObject) | |
フレームワーク | /System/Library/Frameworks/Foundation.framework |
使用可能 | OS X 10.7以降 |
iOS 5.0以降 | |
定義 | NSKeyValueCoding.h |
NSKeyValueObserving.h | |
NSOrderedSet.h |
概要
順序があり要素の重複は許さないコレクションクラスです。順序付きのNSSetのような感じですがNSSetのサブクラスではありません。
このクラスは作成・初期化した後に変更する事はできません。変更可能な順序付きセットはNSMutableOrderedSetクラスを使います。
順序付きセットの作成
順序付きセットの作成はいくつかの方法があります。まず配列から作成する方法ですがオプションなしの(+ orderedSetWithArray)メソッドがあります。オプション付きの(+ orderedSetWithArray:range:copyItems)メソッドは配列の範囲を指定できます。通常順序付きセットに含まれる要素はコピーされないのですが、copyItems:にYESを渡すと要素がコピーされて順序付きセットに保持されます。
要素をコピーして順序付きセットを作る例
#pragma mark NSOrderedSet orderedSetWithArray:range:copyItems: -(void)method002 { NSMutableString *aaa = [NSMutableString stringWithString:@"aaa"]; NSMutableString *bbb = [NSMutableString stringWithString:@"bbb"]; NSMutableString *ccc = [NSMutableString stringWithString:@"ccc"]; NSLog(@"%s %p %@",__FUNCTION__,aaa,aaa); NSLog(@"%s %p %@",__FUNCTION__,bbb,bbb); NSLog(@"%s %p %@",__FUNCTION__,ccc,ccc); //=>0x6e73fd0 aaa //=>0x6e736f0 bbb //=>0x6e73730 ccc NSArray *aArray = [NSArray arrayWithObjects:aaa,bbb,ccc, nil]; NSOrderedSet *aOrderedSet = [NSOrderedSet orderedSetWithArray:aArray range:NSMakeRange(0,3) copyItems:YES]; [aOrderedSet enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { NSLog(@"%s %p %@",__FUNCTION__, obj ,obj); if ([obj isEqualToString:@"ggg"]) { *stop = YES; } }]; //=>0xb52bfe0 aaa //=>0xb52eb30 bbb //=>0xb52fb30 ccc }
オブジェクトから順序付きセットを作るメソッド(+ orderedSetWithObject)や、複数オブジェクトから順序付きセットを作るメソッド(+ orderedSetWithObjects)があります。
C配列から順序付きセットを作るメソッド(+ orderedSetWithObjects:count)も用意されています。
順序付きセットから順序付きセットを作成するメソッド(+ orderedSetWithOrderedSet)があります。オプション付きのメソッド(+ orderedSetWithOrderedSet:range:copyItems)もあります。copyItems:にYESを渡す事で、要素がコピーされます。
セットオブジェクトから順序付きセットを作成するメソッド(+ orderedSetWithSet)があります。オプション付きのメソッド(+ orderedSetWithSet:copyItems)もあります。
変更可能な順序付きセット(NSMutableOrderedSet)の作成のためのメソッド(+ orderedSet)もこのクラスに定義されています。
順序付きセットの初期化
allocで作成した後、配列から順序付きセットを初期化するメソッド(– initWithArray)があります。copyItems:にYESを渡すことで、要素がコピーされるメソッド(– initWithArray:copyItems)もあります。配列の範囲を指定して順序付きセットを初期化するメソッド(– initWithArray:range:copyItems)もあります。
allocで作成した後、オブジェクトから順序付きセットを初期化するメソッド(– initWithObject)があります。複数オブジェクトから順序付きセットを初期化するメソッド(– initWithObjects)もあります。C配列から順序付きセットを初期化するメソッド(– initWithObjects:count)もあります。
allocで作成した後順序付きセットから順序付きセットを初期化するメソッド(– initWithOrderedSet)があります。copyItems:にYESを渡すことで要素がコピーされるメソッド(– initWithOrderedSet:copyItems)や範囲を指定できるメソッド(– initWithOrderedSet:range:copyItems)があります。
allocで作成した後セットオブジェクトから順序付きセットを初期化するメソッド(– initWithSet)があります。copyItems:にYESを渡すことで要素がコピーされるメソッド(– initWithSet:copyItems)もあります。
要素へのアクセス
順序付きセットの要素を順番にとりだしていく方法ですが、NSEnumeratorを使う方法とブロックオブジェクトを使う方法があります。まずブロックを使う方法ですが基本的なメソッド(– enumerateObjectsUsingBlock)があり、オプションをつけることができるメソッド(– enumerateObjectsWithOptions:usingBlock)があります。オプション(NSEnumerationOptions)は並列処理を行う・逆順で行うの2種類が定義されています。それに加えてアクセスする要素を指定することができるメソッド(– enumerateObjectsAtIndexes:options:usingBlock)があります。インデックスセット(NSIndexSet)でアクセスする要素を番号の範囲で指定します。
要素を指定してアクセス
#pragma mark NSOrderedSet enumerateObjectsAtIndexes:options:usingBlock: -(void)method015 { NSMutableString *aaa = [NSMutableString stringWithString:@"aaa"]; NSMutableString *bbb = [NSMutableString stringWithString:@"bbb"]; NSMutableString *ccc = [NSMutableString stringWithString:@"ccc"]; NSMutableString *ddd = [NSMutableString stringWithString:@"ddd"]; NSMutableString *eee = [NSMutableString stringWithString:@"eee"]; NSMutableString *fff = [NSMutableString stringWithString:@"fff"]; NSArray *aArray = [NSArray arrayWithObjects:aaa,bbb,ccc,ddd,eee,fff, nil]; NSOrderedSet *anOrderedSet = [[NSOrderedSet alloc] initWithArray:aArray]; NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2,4)]; [anOrderedSet enumerateObjectsAtIndexes:indexSet options:NSEnumerationConcurrent usingBlock:^(id obj, NSUInteger idx, BOOL *stop) { NSLog(@"%s %p %@",__FUNCTION__, obj ,obj); if ([obj isEqualToString:@"eee"]) { *stop = YES; } }]; }
次にNSEnumeratorを使う方法です。順序付きセットから列挙子オブジェクト(NSEnumerator)を作成するメソッド(– objectEnumerator)を使い、NSEnumeratorを作成します。その後ループを回して一つずつ調べていきます。逆順の列挙子オブジェクトを作成するメソッド(– reverseObjectEnumerator)もあります。
NSEnumeratorを使った要素のチェック
#pragma mark NSOrderedSet objectEnumerator -(void)method016 { NSMutableString *aaa = [NSMutableString stringWithString:@"aaa"]; NSMutableString *bbb = [NSMutableString stringWithString:@"bbb"]; NSMutableString *ccc = [NSMutableString stringWithString:@"ccc"]; NSMutableString *ddd = [NSMutableString stringWithString:@"ddd"]; NSMutableString *eee = [NSMutableString stringWithString:@"eee"]; NSMutableString *fff = [NSMutableString stringWithString:@"fff"]; NSArray *aArray = [NSArray arrayWithObjects:aaa,bbb,ccc,ddd,eee,fff, nil]; NSOrderedSet *anOrderedSet = [[NSOrderedSet alloc] initWithArray:aArray]; id obj; NSEnumerator *aEnumerator = [anOrderedSet objectEnumerator]; while ((obj = [aEnumerator nextObject]) != nil) { NSLog(@"%s %p %@",__FUNCTION__, obj ,obj); } }
各要素をチェックして最初に結果がYESの要素の番号を返すメソッド(– indexOfObjectPassingTest)があります。最初に該当した一つの要素の番号を返すことができます。チェック処理はそこで終了します。オプションをつけて並列処理・逆順処理を行うことができるメソッド(– indexOfObjectWithOptions:passingTest)やアクセスする要素を指定することができるメソッド(– indexOfObjectAtIndexes:options:passingTest)があります。インデックスセット(NSIndexSet)でアクセスする要素を番号の範囲で指定します。
上記と同じようなメソッド名で混同しやすいのですが各要素をチェックして結果がYESの要素の番号をNSIndexSetとして返すメソッド(– indexesOfObjectsPassingTest:)があります。こちらは複数の要素の番号を返すことができます。オプションをつけて並列処理・逆順処理を行うことができるメソッド(– indexesOfObjectsWithOptions:passingTest)やアクセスする要素を指定することができるメソッド(– indexesOfObjectsAtIndexes:options:passingTest)があります。インデックスセット(NSIndexSet)でアクセスする要素を番号の範囲で指定します。
要素が@""bbb"であるか、または番号が4より大きいかの要素の番号を返すサンプル。番号が4より大きくなるとテストを停止します。
#pragma mark indexesOfObjectsWithOptions:passingTest: -(void)method018 { NSMutableString *aaa = [NSMutableString stringWithString:@"aaa"]; NSMutableString *bbb = [NSMutableString stringWithString:@"bbb"]; NSMutableString *ccc = [NSMutableString stringWithString:@"ccc"]; NSMutableString *ddd = [NSMutableString stringWithString:@"ddd"]; NSMutableString *eee = [NSMutableString stringWithString:@"eee"]; NSMutableString *fff = [NSMutableString stringWithString:@"fff"]; NSArray *aArray = [NSArray arrayWithObjects:aaa,bbb,ccc,ddd,eee,fff, nil]; NSOrderedSet *anOrderedSet = [[NSOrderedSet alloc] initWithArray:aArray]; NSIndexSet *indexSet = [anOrderedSet indexesOfObjectsWithOptions:NSEnumerationReverse passingTest:^ BOOL (id obj, NSUInteger idx, BOOL *stop) { if (idx > 4) { return YES; *stop = YES; } if ([obj isEqualToString:@"bbb"]) { return YES; }else { return NO; } }]; NSLog(@"%s %@",__FUNCTION__, [indexSet description]); }
指定したオブジェクトを探しその番号を返すメソッド(– indexOfObject)やオプションで目的のオブジェクトがなかった場合の処理を追加できるメソッド(– indexOfObject:inSortedRange:options:usingComparator)があります。単にオブジェクトが順序付きセットに含まれているかどうかが知りたい場合は(– containsObject)メソッドで確認できます。
指定した番号で順序付きセットの要素を取り出すには(– objectAtIndex)メソッドを使用します。NSIndexSetを使って複数の要素を取り出すには(– objectsAtIndexes)メソッドを使用します。最初の要素を取り出すには(– firstObject)メソッドを使用し、最後の要素を取り出すには(– lastObject)メソッドを使用します。
逆順の順序付きセットを取り出すには(– reversedOrderedSet)メソッドを使用します。
C配列に指定した範囲の要素データを渡すメソッド(– getObjects:range)もあります。
順序付きセットをセットオブジェクト(NSSet)にするには(– set)メソッドを使用します。配列オブジェクト(NSArray)にするには(– array)メソッドを使用します。
ソートした配列にするには(– sortedArrayUsingComparator)を使用します。オプション付きの(– sortedArrayWithOptions:usingComparator)メソッドもあります。
セットの比較
2つのセットが全く同じであるかは(– isEqualToOrderedSet)メソッドで調べることができます。レシーバと比較する順序付きセットに重複するところがあるかを調べるには(– intersectsOrderedSet)メソッドを使います。比較する順序付きセットにレシーバの要素がすべて含まれているかを調べるには(– isSubsetOfOrderedSet)メソッドを使います。順序が違っていても同じ要素が含まれていればYESが返されます。セットオブジェクト(NSSet)と比較するメソッド(– intersectsSet)(– isSubsetOfSet)もあります。
キーバリューコーディング
キーバリューコーディングで使用する(– setValue:forKey)(– valueForKey)があります。
キーバリューオブザービング
キーバリューオブザービングで使用する3つのメソッド(– addObserver:forKeyPath:options:context)(– removeObserver:forKeyPath)(– removeObserver:forKeyPath:context)があります。
メソッド
順序付きセットの作成
+ orderedSet
+ orderedSetWithArray
+ orderedSetWithArray:range:copyItems
+ orderedSetWithObject
+ orderedSetWithObjects
+ orderedSetWithObjects:count
+ orderedSetWithOrderedSet
+ orderedSetWithOrderedSet:range:copyItems
+ orderedSetWithSet
+ orderedSetWithSet:copyItems
順序付きセットの初期化
– initWithArray
– initWithArray:copyItems
– initWithArray:range:copyItems
– initWithObject
– initWithObjects
– initWithObjects:count
– initWithOrderedSet
– initWithOrderedSet:copyItems
– initWithOrderedSet:range:copyItems
– initWithSet
– initWithSet:copyItems
要素のカウント
セットの要素へのアクセス
– containsObject
– enumerateObjectsAtIndexes:options:usingBlock
– enumerateObjectsUsingBlock
– enumerateObjectsWithOptions:usingBlock
– firstObject
– lastObject
– objectAtIndex
– objectAtIndexedSubscript
– objectsAtIndexes
– indexOfObject
– indexOfObject:inSortedRange:options:usingComparator
– indexOfObjectAtIndexes:options:passingTest
– indexOfObjectPassingTest
– indexOfObjectWithOptions:passingTest
– indexesOfObjectsAtIndexes:options:passingTest
– indexesOfObjectsPassingTest
– indexesOfObjectsWithOptions:passingTest
– objectEnumerator
– reverseObjectEnumerator
– reversedOrderedSet
– getObjects:range
キーバリューコーディング
キーバリュー監視
– addObserver:forKeyPath:options:context
– removeObserver:forKeyPath
– removeObserver:forKeyPath:context
定数
関連記事
NSArrayとNSOrderedSet - NSTrivial
Objective-Cで配列の要素の重複を取り除く方法 NSOrderedSetを用いる | 川崎に住んでるアプリ開発(予定)者のブログ
Using an Instance of NSOrderedSet from Swift
レベルアップObjective-C - 沼田哲史 - Google ブックス
Objective-C - NSArrayの差分を取る - Qiita
iOS SDK プログラミング・リファレンス: 【Foundation/UIKit編】 - 大森智史, 中野洋一 - Google ブックス
Objective-C für Einsteiger - 36 - NSOrderedSet (Xcode, iPhone, iPad, Objective-C) - YouTube
NSFetchedResultsControllerとNSOrderedSet関係 -- IT専門質問の答え -- 彼山の知識