Download - Talks on collections
“Let’s talk collections”
или кое-что о коллекциях в iOS.
Наиболее часто используемые
коллекции•массивы: NS(Mutable)Array
•словари: NS(Mutable)Dictionary
•множества (наборы): NS(Mutable)Set
•упорядоченные множества: NS(Mutable)OrderedSet
iOS 2.0
iOS 5.0
Кое-что редко используемое
•NSPointerArray
•NSMapTable
•NSHashTable
• СF(Mutable)ArrayRef
• СF(Mutable)DictionaryRef
• СF(Mutable)SetRef
• CF(Mutable)BagRef
• CFTreeRef, CFBinaryHeapRef
iOS 6.0
➡NS(Mutable)Array
➡NS(Mutable)Dictionary
➡NS(Mutable)Set
NSCountedSet
N/A
Специализированные коллекции
• NS(Mutable)IndexSet
• NS(Mutable)CharacterSet / CF(Mutable)CharacterSetRef
• CF(Mutable)BitVector
Прочее•Массивы C, ex: int array[] = { 10, 20 };
•STL, Boost, etc., ex: std::vector<int> arr;
•Сторонние библиотеки:
‣ ReactiveCocoa
‣ NSEnumeratorLinq (After MS LINQ)
‣ Underscore.m (After Underscore.js)
‣ SOCQ
‣ ... etc
Новое в работе с коллекциями iOS 6
ЭлеменЭлементт
Версия Версия LLVM/iOLLVM/iO
SSПримерПример
Литералы
4/all
@[ @10, @YES, @"String" ]@{ @"Key 1" : @"Value 1", @10 : @YES }
+ (id)arrayWithObjects:(const id[])objects count:(NSUInteger)count;
+ (id)dictionaryWithObjects:(const id[])objects forKeys:(const id<NSCopying>[])keys count:(NSUInteger)count;
Индексация 4/iOS 5
array[index / 2] = @(index << 1)dict[key] = @NO
- (id)objectAtIndexedSubscript:(NSUInteger)idx;- (id)objectForKeyedSubscript:(id)key;
- (void)setObject:(id)objatIndexedSubscript:(NSUInteger)idx;
- (void)setObject:(id)objforKeyedSubscript:(id<NSCopying>)key;
Shared Key Sets x/6
// Immutable dictionary+ (id)sharedKeySetForKeys:(NSArray *)keys;// Mutable dictionary+ (id)dictionaryWithSharedKeySet:(id)set;
Что есть NSArray?NSArray
NSMutableArray
__NSArrayM
__NSCFArray
__NSPlaceholderArray
NSKeyValueMutableArray
NSKeyValueSlowMutableArray
NSKeyValueNotifyingMutableArray
NSKeyValueIvarMutableArray
NSKeyValueFastMutableArray
NSKeyValueFastMutableArray1
NSKeyValueFastMutableArray2
NSKeyValueArray
__NSArrayI
__NSArrayReversed
@interface __NSArrayM : NSMutableArray { unsigned int _size : 30; unsigned int _offset : 30; id *_list; unsigned long _mutations; ... ... ...}
@end
Препарируя NSArray...
- (void)rollObjectsInRange:(NSRange *)range by:(int)number;
- (void)trimObjectsFromIndex:(unsigned)index;
Интересные методы в NS(Mutable)Array+ (id)arrayWithFloats:(float *)items count:(NSUInteger)count;
+ (id)arrayWithInts:(int *)items count:(NSUInteger)count;
- (BOOL)_validateValue:(id __unsafe_unretained *)value forKeyPath:(NSString *)keyPath ofObjectAtIndex:(NSUInteger)index error:(id *)error;- (id)_mutableArrayValueForKeyPath:(NSString *)keyPath ofObjectAtIndex:(NSUInteger)index;- (id)_mutableSetValueForKeyPath:(NSString *)keyPath ofObjectAtIndex:(NSUInteger)index;
- (id)_valueForKeyPath:(NSString *)keyPath ofObjectAtIndex:(NSUInteger)index;- (void)_setValue:(id)value forKeyPath:(NSString *)keyPath ofObjectAtIndex:(NSUInteger)index;
- (BOOL)_kb_firstTwoObjectsEqual;- (NSArray *)allObjectsWithClass:(Class)class;- (id)arrayByApplyingSelector:(SEL)selector;- (id)arrayByExcludingObjectsInArray:(NSArray *)objects;- (id)arrayByReversingOrder;- (NSUInteger)indexOfSmallestObject;- (id)repeatedNTimes:(int)N;
- (void)enqueueObject:(id)object;- (id)dequeueObject;- (id)pop;- (void)push:(id)object;- (void)removeFirstObject;- (void)shuffle;
Showtime
Новые коллекции в iOS 6ТипТип НазначениеНазначение
NSPointerArray
Коллекция, могущая содержать NULL; позволяющая задавать собственный размер непосредственно. Позволяет
задавать правила управления элементами: как памятью, так и
интерпретацией.
NSMapTable
Позволяет иметь слабые ссылки как на ключи, так и на значения. Позволяет
копировать/не копировать ключи/значения. Класть в нее можно и простые указатели. Все настраивается.
NSHashTable
Позволяет иметь слабые ссылки на значения. Позволяет копировать/не копировать значения. Класть в нее
можно и простые указатели. Все настраивается.
Создание и использование
NSPointerArray, ...- (id)initWithOptions:(NSPointerFunctionsOptions)options;
+ (id)initWithPointerFunctions:(NSPointerFunctions *)functions;+ (id)strongObjectsPointerArray;+ (id)weakObjectsPointerArray;
- (void)addPointer:(void *)pointer;- (void)removePointerAtIndex:(NSUInteger)index;- (void)insertPointer:(void *)item atIndex:(NSUInteger)index;- (void)replacePointerAtIndex:(NSUInteger)index withPointer:(void *)item;- (void *)pointerAtIndex:(NSUInteger)index;- (NSArray *)allObjects;
- (void)setCount:(NSUInteger)count;- (void)compact;
... NSMapTable, ...- (id)initWithKeyOptions:(NSPointerFunctionsOptions)keys valueOptions:(NSPointerFunctionsOptions)values capacity:(NSUInteger)capacity;
- (id)initWithKeyPointerFunctions:(NSPointerFunctions *)keyFunctions valuePointerFunctions:(NSPointerFunctions *)valueFunctions capacity:(NSUInteger)capacity;
+ (id)mapTableWithKeyOptions:(NSPointerFunctionsOptions)keyOptions valueOptions:(NSPointerFunctionsOptions)valueOptions;
+ (id)strongToStrongObjectsMapTable;+ (id)strongToWeakObjectsMapTable;+ (id)weakToStrongObjectsMapTable;+ (id)weakToWeakObjectsMapTable;
- (void)setObject:(id)value forKey:(id)key;- (void)removeObjectForKey:(id)key;
- (NSDictionary *)dictionaryRepresentation;
... NSHashTable.- (id)initWithOptions:(NSPointerFunctionsOptions)options capacity:(NSUInteger)capacity;
- (id)initWithPointerFunctions:(NSPointerFunctions *)functions capacity:(NSUInteger)capacity;
+ (id)hashTableWithOptions:(NSPointerFunctionsOptions)options;+ (id)weakObjectsHashTable;
- (void)addObject:(id)object;- (void)removeObject:(id)object;
- (NSArray *)allObjects;- (id)anyObject;- (BOOL)containsObject:(id)object;- (id)member:(id)object;
- (NSSet *)setRepresentation;
- (BOOL)intersectsHashTable:(NSHashTable *)other;- (BOOL)isSubsetOfHashTable:(NSHashTable *)other;
- (void)intersectHashTable:(NSHashTable *)other;- (void)minusHashTable:(NSHashTable *)other;- (void)unionHashTable:(NSHashTable *)other;
NSPointerFunctionsOptions
typedef NS_OPTIONS(NSUInteger, NSPointerFunctionsOptions) { NSPointerFunctionsStrongMemory = (0 << 0), NSPointerFunctionsOpaqueMemory = (2 << 0), NSPointerFunctionsMallocMemory = (3 << 0), NSPointerFunctionsMachVirtualMemory = (4 << 0), NSPointerFunctionsWeakMemory = (5UL << 0),
NSPointerFunctionsObjectPersonality = (0 << 8), NSPointerFunctionsOpaquePersonality = (1 << 8), NSPointerFunctionsObjectPointerPersonality = (2 << 8), NSPointerFunctionsCStringPersonality = (3 << 8), NSPointerFunctionsStructPersonality = (4 << 8), NSPointerFunctionsIntegerPersonality = (5 << 8),
NSPointerFunctionsCopyIn = (1 << 16),};
NSMapTableOptions, NSHashTableOptions
typedef NS_OPTIONS(NSUInteger, NSMapTableOptions) { NSMapTableStrongMemory = 0, NSMapTableCopyIn = NSPointerFunctionsCopyIn, NSMapTableWeakMemory = NSPointerFunctionsWeakMemory
NSMapTableObjectPointerPersonality = NSPointerFunctionsObjectPointerPersonality,};
typedef NS_OPTIONS(NSUInteger, NSHashTableOptions) { NSHashTableStrongMemory = 0, NSHashTableCopyIn = NSPointerFunctionsCopyIn, NSHashTableWeakMemory = NSPointerFunctionsWeakMemory
NSHashTableObjectPointerPersonality = NSPointerFunctionsObjectPointerPersonality,};
Showtime
Коллекции и KVC I
- (id)valueForKey:(NSString *)key;- (void)setValue:(id)value forKey:(NSString *)key;
- (id)valueForKeyPath:(NSString *)keyPath;- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
- (NSMutableArray *)mutableArrayValueForKeyPath:(NSString *)keyPath;- (NSMutableSet *)mutableSetValueForKeyPath:(NSString *)keyPath;- (NSMutableOrderedSet *)mutableOrderedSetValueForKeyPath:(NSString *)keyPath;
- (BOOL)validateValue:(inout id *)value forKeyPath:(NSString *)keyPath error:(out NSError * __autoreleasing *)error;
Коллекции и KVC II- (id)valueForKey:- (id)valueForKey:(NSString *)key;(NSString *)key;
- (void)setValue:- (void)setValue:(id)value forKey:(id)value forKey:(NSString *)key;(NSString *)key;
NSDictionary (I/M)NSDictionary (I/M) То же, что и objectForKey:
setObject:forKey:, если value != nil; иначе,
removeObjectForKey:
NSArray (I/M)NSArray (I/M)
Массив результатов valueForKey: над
каждым элементом (NSNull если nil).
setValue:forKey: над каждым элементом.
NSSet (I/M)NSSet (I/M)
Множество результатов valueForKey: над
каждым элементом (nil опускается, дубликаты
опускаются).
NSOrderedSet (I/M)NSOrderedSet (I/M)
Упорядоченное множество результатов
valueForKey: над каждым элементом (nil опускается, дубликаты
опускаются).
Коллекции и KVC IIIPerson *oldestPerson = [people valueForKeyPath:@"@max.age"];
NSArray *uniqueNamesOfSiblings = [person valueForKeyPath:@"[email protected]"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name BEGINSWITH 'J' AND age >= 18"];NSArray *allAdultJs = [people filteredArrayUsingPredicate:predicate];
NSPredicate *predicate = [NSPredicate predicateWithFormat: @"FUNCTION(SELF, \"capitalizedString\") BEGINSWITH[cd] 'H'" ];NSArray *startingFromCapitalH = [ @[ @"hello", @"world" ] filteredArrayUsingPredicate:predicate];
Доступные функции KVC
ФункцияФункция Методы NSArrayМетоды NSArray @avg - (id)_avgForKeyPath:(NSString *)keyPath;
@count - (id)_countForKeyPath:(NSString *)keyPath;
@distinctUnionOfArrays - (id)_distinctUnionOfArraysForKeyPath:(NSString *)keyPath;
@distinctUnionOfObjects - (id)_distinctUnionOfObjectsForKeyPath:(NSString *)keyPath;
@distinctUnionOfSets - (id)_distinctUnionOfSetsForKeyPath:(NSString *)keyPath;
@max - (id)_maxForKeyPath:(NSString *)keyPath;
@min - (id)_minForKeyPath:(NSString *)keyPath;
@sum - (id)_sumForKeyPath:(NSString *)keyPath;
@unionOfArrays - (id)_unionOfArraysForKeyPath:(NSString *)keyPath;
@unionOfObjects - (id)_unionOfObjectsForKeyPath:(NSString *)keyPath;
@unionOfSets - (id)_unionOfSetsKeyPath:(NSString *)keyPath;
Что есть предикаты?
NSPredicate
NSCompoundPredicate
NSComparisonPredicate
NSBlockPredicate
NSTruePredicate
NSFalsePredicate
Создание предикатов+ (P)predicateWithFormat:(S)predicateFormat, ...
+ (P)andPredicateWithSubpredicates:(A)subpredicates;
+ (P)orPredicateWithSubpredicates:(A)subpredicates;
+ (P)notPredicateWithSubpredicate:(P)predicate;
+ (P)predicateWithLeftExpression:(E)lhs rightExpression:(E)rhs modifier:(NSComparisonPredicateModifier)modifier type:(NSPredicateOperatorType)type options:(NSComparisonPredicateOptions)options;
+ (P)predicateWithLeftExpression:(E)lhs rightExpression:(E)rhs customSelector:(SEL)selector;typedef NS_OPTIONS(NSUInteger, NSComparisonPredicateOptions) { NSCaseInsensitivePredicateOption, NSDiacriticInsensitivePredicateOption, NSNormalizedPredicateOption};
typedef NS_ENUM(NSUInteger, NSComparisonPredicateModifier) { NSDirectPredicateModifier, NSAllPredicateModifier, NSAnyPredicateModifier};
typedef NS_ENUM(NSUInteger, NSPredicateOperatorType) { NSLessThanPredicateOperatorType, NSLessThanOrEqualToPredicateOperatorType, NSGreaterThanPredicateOperatorType, NSGreaterThanOrEqualToPredicateOperatorType, NSEqualToPredicateOperatorType, NSNotEqualToPredicateOperatorType, NSMatchesPredicateOperatorType, NSLikePredicateOperatorType, NSBeginsWithPredicateOperatorType, NSEndsWithPredicateOperatorType, NSInPredicateOperatorType, NSCustomSelectorPredicateOperatorType, NSContainsPredicateOperatorType, NSBetweenPredicateOperatorType};
ВыраженияNSExpression
NSAggregateExpression
NSAnyKeyExpression
NSBlockExpression
NSConstantValueExpression
NSFunctionExpression
NSKeyPathExpression
NSKeyPathSpecifierExpression
NSSelfExpression
NSSetExpression
NSSubqueryExpression
NSSymbolicExpression
NSTernaryExpression
NSVariableAssignmentExpression
NSVariableExpression
+(E)expressionForBlock:(id(^)(id evaluatedObject, NSArray *expressions, NSMutableDictionary *context))block arguments:(NSArray *)arguments;
+(E)expressionForAggregate:(A)values;+(E)expressionForConstantValue:(id)value;+(E)expressionForEvaluatedObject;+(E)expressionForVariable:(S)variable;+(E)expressionForKeyPath:(S)keyPath;
+(E)expressionForFunction:(S)name arguments:(A)arguments;
+(E)expressionForFunction:(S)name selectorName:(S)selectorName arguments:(A)arguments;
+(E)expressionForIntersectSet:(E)left with:(E)right;+(E)expressionForMinusSet:(E)left with:(E)right;+(E)expressionForUnionSet:(E)left with:(E)right;
+(E)expressionForSubquery:(E)expression usingIteratorVariable:(S)variable predicate:(P)predicate;
+(E)expressionForSymbolicString:(S)string;+(E)expressionForTernaryWithPredicate:(P)predicate trueExpression:(E)te falseExpression:(E)fe;+(E)expressionForVariableNameAssignment:(S)variableName expression:(E)expression;
Функции предикатов
ЛитералЛитерал МетодМетод
+, -, *, /, %
add:to:from:subtract:multiply:by:divide:by:modulus:by:
**, <<, >>, sqrt(v)
raise:toPower:leftshift:by:rightshift:by:sqrt:
&, |, ^, ~bitwiseAnd:with:bitwiseOr:with:bitwiseXor:with:onesComplement:
CAST(value, “TYPE”)
castObject:toType:
ceiling(v), floor(v), trunc(v)
ceiling:floor:trunc:
random, randomn(v)
randomrandomn:
now now
ЛитералЛитерал МетодМетодmin(a), max(a), sum(a)
min:max:sum:
average(a),stddev(a),median(a),mode(a)
average:stddev:median:mode:
a[SIZE]a[index]
count:objectFrom:withIndex:
DISTINCTnoindex(v)
distinct:noindex:
exp(v), ln(v), log(v), abs(v)
exp:ln:log:abs:
lowercase(v), uppercase(v)
lowercase:uppercase:
Showtime
Коллекции и KVO INSArray/NSArray/
NSMutableArrayNSMutableArrayKVC-ComplianceKVC-Compliance
NSSet/NSMutableSetNSSet/NSMutableSetKVC-ComplianceKVC-Compliance
•Импелементировать -<key>.•ИЛИ завести ivar <key> или _<key>.•ИЛИ имплементировать -countOf<Key>
И один или оба -objectIn<Key>AtIndex: и/или -<key>AtIndexes:.
•Для улучшения производительности имплементировать -get<Key>:range:.
•Импелементировать -<key>.•ИЛИ завести ivar <key> или _<key>.•ИЛИ имплементировать -countOf<Key>, -enumeratorOf<Key>, и -memberOf<Key>
•Импелементировать один или оба -insertObject:in<Key>AtIndex: и/или -
insert<Key>:atIndexes:.•Импелементировать один или оба -
removeObjectFrom<Key>AtIndex: и/или -
remove<Key>AtIndexes:.•Для улучшения производительности
имплементировать -replaceObjectIn<Key>AtIndex:withObject: и/или
-replace<Key>AtIndexes:with<Key>:.
•Импелементировать один или оба -add<Key>Object: и/или -add<Key>:.
•Импелементировать один или оба -remove<Key>Object: и/или -remove<Key>:.
•Для улучшения производительности имплементировать
-intersect<Key>: и/или -set<Key>:.
Коллекции и KVO II
•NSArray, NSOrderedSet, NSSet:
‣Нельзя вызывать addObserver:forKeyPath:options:context:
•NSArray
‣Можно вызывать addObserver:toObjectsAtIndexes:forKeyPath:options:context:
•NSDictionary
‣Можно вызывать addObserver:forKeyPath:options:context:
Коллекции и KVO III- (void)willChangeValueForKey:(NSString *)key;
- (void)willChange:(NSKeyValueChange)change valuesAtIndexes:(NSIndexSet *)indexes forKey:(NSString *)key;
- (void)willChangeValueForKey:(NSString *)key withSetMutation:(NSKeyValueSetMutationKind)mutationKind usingObjects:(NSSet *)objects;
- (void)didChangeValueForKey:(NSString *)key;
- (void)didChange:(NSKeyValueChange)change valuesAtIndexes:(NSIndexSet *)indexes forKey:(NSString *)key;
- (void)didChangeValueForKey:(NSString *)key withSetMutation:(NSKeyValueSetMutationKind)mutationKind usingObjects:(NSSet *)objects;
typedef NS_OPTIONS(NSUInteger, NSKeyValueChange) { NSKeyValueChangeSetting, NSKeyValueChangeInsertion, NSKeyValueChangeRemoval, NSKeyValueChangeReplacement};typedef NS_OPTIONS(NSUInteger, NSKeyValueSetMutationKind) { NSKeyValueUnionSetMutation, NSKeyValueMinusSetMutation, NSKeyValueIntersectSetMutation, NSKeyValueSetSetMutation};
NSString *const NSKeyValueChangeKindKey;NSString *const NSKeyValueChangeNewKey;NSString *const NSKeyValueChangeOldKey;NSString *const NSKeyValueChangeIndexesKey;NSString *const NSKeyValueChangeNotificationIsPriorKey;
typedef NS_OPTIONS(NSUInteger, NSKeyValueObservingOptions) { NSKeyValueObservingOptionNew, NSKeyValueObservingOptionOld, NSKeyValueObservingOptionInitial, NSKeyValueObservingOptionPrior};
Showtime
Core Foundation•CFArrayRef / CFMutableArrayRef
•CFDictionaryRef / CFMutableDictionaryRef
•CFSetRef / CFMutableSetRef
•CFBagRef / CFMutableBagRef
•CFTreeRef
•CFBinaryHeapRef
Особенности CF-коллекций
ОсобенностьОсобенность Способ определенияСпособ определения
Могут быть как fixed-size, так и variable-size.
CFArrayCreateMutable( kCFAllocatorDefault, <NUMBER_OF_ITEMS>, &kCFTypeArrayCallBacks);Если <NUMBER_OF_ITEMS> == 0, то variable-size
Поведение при добавлении/удалении/по
иске элементов определяется при
создании.
CFArrayCallBacks,CFDictionaryKeyCallBacks,CFDictionaryValueCallBacks,CFSetCallBacks,CFBagCallBacks,CFTreeContext,CFBinaryHeapCallBacks/CFBinaryHeapCompareContext
CF(Mutable)ArrayRef, CF(Mutable)DictionaryRef,CF(Mutable)SetRef - toll-
free bridged.
CFArrayRef a = (__bridge_retained CFArrayRef)[NSArray new];CFArrayRef a = (__bridge CFArrayRef)[NSArray array];NSArray *a = (__bridge_transfer NSArray *) CFArrayCreate( 0, (const void **) &(CFStringRef *){ CFSTR("1"), NULL }, 2, NULL);
Можно класть NULL или ints с размерностью
указателя.
КоллекциКоллекцияя
CallbackCallback PredefinedPredefined
ArrayArraytypedef struct { CFIndex version; CFArrayRetainCallBack retain; CFArrayReleaseCallBack release; CFArrayCopyDescriptionCallBack copyDescription; CFArrayEqualCallBack equal;} CFArrayCallBacks;
kCFTypeArrayCallBacks
DictionaryDictionary
typedef struct { // ...Like in prefixed prefixed CFDictionary CFDictionaryHashCallBack hash;} CFDictionaryKeyCallBacks;
typedef struct { // ...Like in array prefixed CFDictionary} CFDictionaryValueCallBacks;
kCFTypeDictionaryKeyCallBackskCFCopyStringDictionaryKeyCallBackskCFTypeDictionaryValueCallBacks
Set/BagSet/Bagtypedef struct { // ...Like in dictionary but prefixed CFSet/CFBag} CFSet(Bag)CallBacks;
kCFTypeSetCallBackskCFCopyStringSetCallBackskCFTypeBagCallBackskCFCopyStringBagCallBacks
TreeTreetypedef struct { CFIndex version; void *info; CFTreeRetainCallBack retain; CFTreeReleaseCallBack release; CFTreeCopyDescriptionCallBack copyDescription;} CFTreeContext;
Binary Binary HeapHeap
typedef struct { CFIndex version; const void *(*retain) (CFAllocatorRef allocator, const void *ptr); void (*release) (CFAllocatorRef allocator, const void *ptr); CFStringRef (*copyDescription)(const void *ptr); CFComparisonResult (*compare) (const void *ptr1, const void *ptr2, void *context);} CFBinaryHeapCallBacks;
kCFStringBinaryHeapCallBacks
Эффективность реализацииВставкаВставка
worst/avgworst/avgДоступДоступ
worst/avgworst/avgПоискПоиск
worst/avgworst/avg
CFArrayCFArray O(N*lg N) / O(N) O(lg N) / O(1)O(N*lg N) /< O(N*lg N)
CFDictionaCFDictionaryry
O(N*N) / O(1) < O(N) O(N) / O(1)
CFSetCFSet O(N*N) / O(1) < O(N) O(N) / O(1)
CFBagCFBag O(N*N) / O(1) < O(N) O(N) / O(1)
CFTreeRef•Связь от одного parent к N children.
•Parent - владелец children. У children - слабые ссылки на Parent.
•Root тот, у кого нет ссылки на Parent.
•Контекст, заданный при создании Node, определяет правила управления памятью и получения описания над этим Node.
•Как правило, в функции работы с деревьями передается указатель на Parent Node, а операция осуществляется в отношении Child Node.
CFBinaryHeap•Хранит значения в отсортированном виде.
•Любое новое значение встраивается в порядок, сохраняя сортировку.
•Позволяет скорейшим образом получить минимум набора значений, но не максимум (особенности реализации).
•Функция сравнения задается в поле compare в описателе при создании CFBinaryHeap.
•Правила управления памятью объектов в коллекции также задаются в описателе.
Showtime
That’s all, folks!• http://opensource.apple.com/source/CF/CF-744
.12/
• http://funwithobjc.tumblr.com/post/2922267976/using-custom-functions-with-nsexpression
• http://kickingbear.com/blog/archives/9
• https://github.com/nst/iOS-Runtime-Headers
• Apple Documentation• Презентация на Slideshare: http://www.slideshare.net/comfly/talks-on-collections
• Код на Github: https://github.com/comfly/CollectionSamples