Created
June 12, 2013 19:37
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // 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