Skip to content

Instantly share code, notes, and snippets.

@BigAB
Created June 12, 2013 19:37
Show Gist options
  • Select an option

  • Save BigAB/5768407 to your computer and use it in GitHub Desktop.

Select an option

Save BigAB/5768407 to your computer and use it in GitHub Desktop.
A way to create custom Collections of certain objects, that have array like qualities and are easily observed for changes. Inspired by Josh Wright/BendyTree's iOS library https://github.com/bendytree/iOS.
//
// ABCustomCollections.h
//
// Created by BigAB 1/6/2013
// Inspired by Josh Wright/BendyTree's iOS library
// https://github.com/bendytree/iOS
//
#define CUSTOMCOLLECTION_INTERFACE(classname) \
@interface classname ## Collection : CustomCollection \
@property (nonatomic, readonly) Class collectionType; \
- (void) add:(classname*)obj;\
- (classname*) getItemAtIndex:(int)index;\
@end\
#define CUSTOMCOLLECTION_IMPLEMENTATION(classname) \
@implementation classname ## Collection\
- (Class) collectionType{\
return [classname class];\
}\
- (void) add:(classname*)obj{\
[self addObject:obj];\
}\
- (classname*) getItemAtIndex:(int)index {\
return [self objectAtIndex:index];\
}\
@end\
#define CUSTOM_COLLECTION_CHANGE @"CollectionChangeNotificationName"
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface CustomCollection : NSArray
@property (retain) NSMutableArray* array;
#pragma mark - Custom Collection Methods
- (void)setValue:(id)value forKey:(NSString *) key;
- (void)addChangeObserver:(NSObject *)observer withBlock:(void (^)())callback;
- (void)removeObserver:(NSObject *)observer;
#pragma mark - Methods from NSMutableArray & NSArray
//enumeration
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len;
//@interface NSArray (NSExtendedArray)
- (NSArray *)arrayByAddingObject:(id)anObject;
- (NSArray *)arrayByAddingObjectsFromArray:(NSArray *)otherArray;
- (NSString *)componentsJoinedByString:(NSString *)separator;
- (BOOL)containsObject:(id)anObject;
- (NSString *)description;
- (NSString *)descriptionWithLocale:(id)locale;
- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level;
- (id)firstObjectCommonWithArray:(NSArray *)otherArray;
- (void)getObjects:(id __unsafe_unretained [])objects range:(NSRange)range;
- (NSUInteger)indexOfObject:(id)anObject;
- (NSUInteger)indexOfObject:(id)anObject inRange:(NSRange)range;
- (NSUInteger)indexOfObjectIdenticalTo:(id)anObject;
- (NSUInteger)indexOfObjectIdenticalTo:(id)anObject inRange:(NSRange)range;
- (BOOL)isEqualToArray:(NSArray *)otherArray;
- (id)lastObject;
- (NSEnumerator *)objectEnumerator;
- (NSEnumerator *)reverseObjectEnumerator;
- (NSData *)sortedArrayHint;
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context;
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context hint:(NSData *)hint;
- (NSArray *)sortedArrayUsingSelector:(SEL)comparator;
- (NSArray *)subarrayWithRange:(NSRange)range;
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;
- (BOOL)writeToURL:(NSURL *)url atomically:(BOOL)atomically;
- (void)makeObjectsPerformSelector:(SEL)aSelector;
- (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(id)argument;
- (NSArray *)objectsAtIndexes:(NSIndexSet *)indexes;
#if NS_BLOCKS_AVAILABLE
- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block NS_AVAILABLE(10_6, 4_0);
- (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts usingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block NS_AVAILABLE(10_6, 4_0);
- (void)enumerateObjectsAtIndexes:(NSIndexSet *)s options:(NSEnumerationOptions)opts usingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block NS_AVAILABLE(10_6, 4_0);
- (NSUInteger)indexOfObjectPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate NS_AVAILABLE(10_6, 4_0);
- (NSUInteger)indexOfObjectWithOptions:(NSEnumerationOptions)opts passingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate NS_AVAILABLE(10_6, 4_0);
- (NSUInteger)indexOfObjectAtIndexes:(NSIndexSet *)s options:(NSEnumerationOptions)opts passingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate NS_AVAILABLE(10_6, 4_0);
- (NSIndexSet *)indexesOfObjectsPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate NS_AVAILABLE(10_6, 4_0);
- (NSIndexSet *)indexesOfObjectsWithOptions:(NSEnumerationOptions)opts passingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate NS_AVAILABLE(10_6, 4_0);
- (NSIndexSet *)indexesOfObjectsAtIndexes:(NSIndexSet *)s options:(NSEnumerationOptions)opts passingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate NS_AVAILABLE(10_6, 4_0);
- (NSArray *)sortedArrayUsingComparator:(NSComparator)cmptr NS_AVAILABLE(10_6, 4_0);
- (NSArray *)sortedArrayWithOptions:(NSSortOptions)opts usingComparator:(NSComparator)cmptr NS_AVAILABLE(10_6, 4_0);
- (NSUInteger)indexOfObject:(id)obj inSortedRange:(NSRange)r options:(NSBinarySearchingOptions)opts usingComparator:(NSComparator)cmp NS_AVAILABLE(10_6, 4_0); // binary search
#endif
//@interface NSArray (NSArrayCreation)
+ (id)array;
+ (id)arrayWithObject:(id)anObject;
+ (id)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;
+ (id)arrayWithObjects:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
+ (id)arrayWithArray:(NSArray *)array;
- (id)initWithObjects:(const id [])objects count:(NSUInteger)cnt;
- (id)initWithObjects:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
- (id)initWithArray:(NSArray *)array;
- (id)initWithArray:(NSArray *)array copyItems:(BOOL)flag;
+ (id)arrayWithContentsOfFile:(NSString *)path;
+ (id)arrayWithContentsOfURL:(NSURL *)url;
- (id)initWithContentsOfFile:(NSString *)path;
- (id)initWithContentsOfURL:(NSURL *)url;
/**************** Mutable Array ****************/
//@interface NSMutableArray : NSArray
- (void)addObject:(id)anObject;
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index;
- (void)removeLastObject;
- (void)removeObjectAtIndex:(NSUInteger)index;
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
//@interface NSMutableArray (NSExtendedMutableArray)
- (void)addObjectsFromArray:(NSArray *)otherArray;
- (void)exchangeObjectAtIndex:(NSUInteger)idx1 withObjectAtIndex:(NSUInteger)idx2;
- (void)removeAllObjects;
- (void)removeObject:(id)anObject inRange:(NSRange)range;
- (void)removeObject:(id)anObject;
- (void)removeObjectIdenticalTo:(id)anObject inRange:(NSRange)range;
- (void)removeObjectIdenticalTo:(id)anObject;
- (void)removeObjectsFromIndices:(NSUInteger *)indices numIndices:(NSUInteger)cnt NS_DEPRECATED(10_0, 10_6, 2_0, 4_0);
- (void)removeObjectsInArray:(NSArray *)otherArray;
- (void)removeObjectsInRange:(NSRange)range;
- (void)replaceObjectsInRange:(NSRange)range withObjectsFromArray:(NSArray *)otherArray range:(NSRange)otherRange;
- (void)replaceObjectsInRange:(NSRange)range withObjectsFromArray:(NSArray *)otherArray;
//- (void)setArray:(NSArray *)otherArray;
- (void)sortUsingFunction:(NSInteger (*)(id, id, void *))compare context:(void *)context;
- (void)sortUsingSelector:(SEL)comparator;
- (void)insertObjects:(NSArray *)objects atIndexes:(NSIndexSet *)indexes;
- (void)removeObjectsAtIndexes:(NSIndexSet *)indexes;
- (void)replaceObjectsAtIndexes:(NSIndexSet *)indexes withObjects:(NSArray *)objects;
#if NS_BLOCKS_AVAILABLE
- (void)sortUsingComparator:(NSComparator)cmptr NS_AVAILABLE(10_6, 4_0);
- (void)sortWithOptions:(NSSortOptions)opts usingComparator:(NSComparator)cmptr NS_AVAILABLE(10_6, 4_0);
#endif
//@interface NSMutableArray (NSMutableArrayCreation)
+ (id)arrayWithCapacity:(NSUInteger)numItems;
- (id)initWithCapacity:(NSUInteger)numItems;
@end
//
// ABCustomCollections.h
//
// Created by BigAB 1/6/2013
// Inspired by Josh Wright/BendyTree's iOS library
// https://github.com/bendytree/iOS
//
#import "ABCustomCollections.h"
#define CUSTOM_COLLECTION_OBSERVER_OBJ_KEY @"ABCustomCollectionObserverObjectKey"
// disable the incomplete-implementation warning
#pragma clang diagnostic ignored "-Wincomplete-implementation"
@implementation CustomCollection
@synthesize array;
#pragma mark - Initialization
- (id)init {
self = [super init];
if (self) {
self.array = [NSMutableArray new];
}
return self;
}
- (id)initWithObjects:(const id [])objects count:(NSUInteger)cnt; {
self = [self init];
self.array = [self.array initWithObjects:objects count:cnt];
return self;
}
- (id)initWithCapacity:(NSUInteger)numItems
{
self = [self init];
self.array = [self.array initWithCapacity:numItems];
return self;
}
#pragma mark - Methods from NS(Mutable)Array
// Forward all Invocations to Array
- (void)forwardInvocation:(NSInvocation *)invocation{
[invocation invokeWithTarget:self.array];
[self collectionChanged];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [NSMutableArray instanceMethodSignatureForSelector:aSelector];
}
- (NSUInteger) count {
return [self.array count];
}
- (id)objectAtIndex:(NSUInteger)index{
return [self.array objectAtIndex:index];
}
#pragma mark - Custom Collection Methods
- (void)setValue:(id)value forKey:(NSString *) key
{
// This is where we can override settings for sub collections (maybe)
[super setValue:value forKey:key];
}
#pragma mark - Notifying Subscribers of changes
- (void)collectionChanged
{
[[NSNotificationCenter defaultCenter] postNotificationName:CUSTOM_COLLECTION_CHANGE object:self];
}
- (void)addChangeObserver:(NSObject *)observer withBlock:(void (^)())callback
{
id observerObj = [[NSNotificationCenter defaultCenter] addObserverForName:CUSTOM_COLLECTION_CHANGE object:self queue:nil usingBlock:callback];
objc_setAssociatedObject(observer, CUSTOM_COLLECTION_OBSERVER_OBJ_KEY, observerObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)removeObserver:(NSObject *)observer
{
id observerObj = objc_getAssociatedObject(self, CUSTOM_COLLECTION_OBSERVER_OBJ_KEY);
if (observerObj) {
[[NSNotificationCenter defaultCenter] removeObserver: observerObj];
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment