Last active
September 17, 2019 12:49
-
-
Save gamenerds/62e7a13b786dcb807507 to your computer and use it in GitHub Desktop.
A category to abstract the details of NSPointerArray
This file contains 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
#import <Foundation/Foundation.h> | |
// This helps deal with NSPointerArray that stores pointers to objects that inherit from NSObject. | |
// Not sure if this will work for other pointer types!! | |
@interface NSPointerArray (Helpers) | |
/** | |
* Adds pointer to the given object to the array. | |
* | |
* @param object Object whose pointer needs to be added to the array. | |
* If a pointer to this object already exists in the array, you get a duplicate. | |
* Call containsObject first if you don't want that to happen. | |
*/ | |
- (void)addObject:(id)object; | |
/** | |
* Checks if pointer to the given object is present in the array. | |
* | |
* @param object Object whose pointer's presence needs to be checked. | |
* | |
* @return YES if pointer to the given object is already present in the array; NO otherwise. | |
*/ | |
- (BOOL)containsObject:(id)object; | |
/** | |
* Removes a pointer that matches the pointer to the passed in object. | |
* | |
* @param object An object that's currently in the array. No ill effects if the object is not in the array. | |
*/ | |
- (void)removeObject:(id)object; | |
- (void)removeAllNulls; | |
@end |
This file contains 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
#import "NSPointerArray+Helpers.h" | |
@implementation NSPointerArray (Helpers) | |
- (void)addObject:(id)object | |
{ | |
[self addPointer:(__bridge void *)object]; | |
} | |
- (BOOL)containsObject:(id)object | |
{ | |
// get passed in object's pointer | |
void * objPtr = (__bridge void *)object; | |
for (NSUInteger i = 0; i < [self count]; i++) { | |
void * ptr = [self pointerAtIndex:i]; | |
if (ptr == objPtr) { | |
return YES; | |
} | |
} | |
return NO; | |
} | |
- (void)removeObject:(id)object | |
{ | |
// get pointer to the passed in object | |
void * objPtr = (__bridge void *)object; | |
int objIndex = -1; | |
for (NSUInteger i = 0; i < [self count]; i++) { | |
void * ptr = [self pointerAtIndex:i]; | |
if (ptr == objPtr) { | |
// pointers equal, found our object! | |
objIndex = i; | |
break; | |
} | |
} | |
// make sure index is non-nil and not outside bounds | |
if (objIndex >= 0 && objIndex < [self count]) { | |
[self removePointerAtIndex:objIndex]; | |
} | |
} | |
- (void)removeAllNulls | |
{ | |
NSMutableSet *indexesToRemove = [NSMutableSet new]; | |
for (NSUInteger i = 0; i < [self count]; i++) { | |
if (![self pointerAtIndex:i]) { // is the pointer null? then remove it | |
[indexesToRemove addObject:@(i)]; | |
} | |
} | |
for (NSNumber *indexToRemove in indexesToRemove) { | |
[self removePointerAtIndex:[indexToRemove unsignedIntegerValue]]; | |
} | |
} | |
@end |
This file contains 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
// Some object that pushes out notifications | |
#import "NSPointerArray+AbstractionHelpers.h" | |
#import "SampleObject.h" | |
@interface SampleObject () | |
@property (nonatomic, strong) NSPointerArray *delegates; | |
@end | |
@implementation SampleObject | |
- (id)init | |
{ | |
if (self = [super init]) { | |
_delegates = [NSPointerArray pointerArrayWithOptions:NSPointerFunctionsWeakMemory]; | |
} | |
return self; | |
} | |
- (void)registerDelegate:(id<YourProtocolHere>)delegate | |
{ | |
if (!delegate) return; | |
[self addDelegate:delegate]; | |
[self startUpdates]; | |
} | |
- (void)removeDelegate:(id<YourProtocolHere>)delegate | |
{ | |
[self.delegates removeObject:delegate]; | |
// if last delegate gets removed, stop listening for updates/nil out depedency objects, if applicable | |
if ([self.delegates count] == 0) { | |
[self stopUpdates]; | |
} | |
} | |
- (void)addDelegate:(id<YourProtocolHere>)delegate | |
{ | |
if (![self.delegates containsObject:delegate]) { | |
[self.delegates addObject:delegate]; | |
} | |
} | |
// ... some SampleObject logic here ... | |
// Helper method that can be called after each round of notifications to see if any delegates left | |
// Delegates can all eventually become nil due to being weak references | |
- (BOOL)shouldUpdatesContinue | |
{ | |
[self.delegates removeAllNulls]; | |
if ([self.delegates count] == 0) { | |
return NO; | |
} | |
return YES; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Super useful category - thanks!
I was wondering about the
- (void)removeAllNulls;
, isn't it the same as the- (void)compact;
which is a part of the NSPointerArray?