Last active
July 5, 2023 09:11
-
-
Save eralston/8010285 to your computer and use it in GitHub Desktop.
An pair of Objective-C categories on NSArray and NSMutableArray that provides a mechanism for weak referencing any type of Objective-C object. This was created when I found a case, referencing protocols, where NSPointerArray did not work for my needs.
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
// | |
// NSMutableArray+WeakArray.h | |
// | |
#import <Foundation/Foundation.h> | |
/// | |
/// Category on NSArray that provides read methods for weak pointers | |
/// NOTE: These methods may scan the whole array | |
/// | |
@interface NSArray(WeakArray) | |
- (__weak id)weakObjectForIndex:(NSUInteger)index; | |
-(id<NSFastEnumeration>)weakObjectsEnumerator; | |
@end | |
/// | |
/// Category on NSMutableArray that provides write methods for weak pointers | |
/// NOTE: These methods may scan the whole array | |
/// | |
@interface NSMutableArray (FRSWeakArray) | |
-(void)addWeakObject:(id)object; | |
-(void)removeWeakObject:(id)object; | |
-(void)cleanWeakObjects; | |
@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
// | |
// NSMutableArray+WeakArray.m | |
// | |
#import "NSArray+WeakArray.h" | |
/// | |
/// A wrapper for a weak pointer, meant to allow for arrays of weak references (that don't suck) | |
/// | |
@interface WAArrayWeakPointer : NSObject | |
@property (nonatomic, weak) NSObject *object; | |
@end | |
@implementation WAArrayWeakPointer | |
@end | |
@implementation NSArray (WeakArray) | |
/// | |
/// Returns the weakly referenced object at the given index | |
/// | |
-(__weak id)weakObjectForIndex:(NSUInteger)index | |
{ | |
WAArrayWeakPointer *ptr = [self objectAtIndex:index]; | |
return ptr.object; | |
} | |
/// | |
/// Gets the weak pointer for the given object reference | |
/// | |
-(WAArrayWeakPointer *)weakPointerForObject:(id)object | |
{ | |
// Linear search for the object in question | |
for (WAArrayWeakPointer *ptr in self) { | |
if(ptr) { | |
if(ptr.object == object) { | |
return ptr; | |
} | |
} | |
} | |
return nil; | |
} | |
/// | |
/// Returns a fast enumeration collection for all of the weakly referenced objects in this collection | |
/// | |
-(id<NSFastEnumeration>)weakObjectsEnumerator | |
{ | |
NSMutableArray *enumerator = [[NSMutableArray alloc] init]; | |
for (WAArrayWeakPointer *ptr in self) { | |
if(ptr && ptr.object) { | |
[enumerator addObject:ptr.object]; | |
} | |
} | |
return enumerator; | |
} | |
@end | |
@implementation NSMutableArray (FRSWeakArray) | |
/// | |
/// Adds a weak reference to the given object to the collection | |
/// | |
-(void)addWeakObject:(id)object | |
{ | |
if(!object) | |
return; | |
WAArrayWeakPointer *ptr = [[WAArrayWeakPointer alloc] init]; | |
ptr.object = object; | |
[self addObject:ptr]; | |
[self cleanWeakObjects]; | |
} | |
/// | |
/// Removes a weakly referenced object from the collection | |
/// | |
-(void)removeWeakObject:(id)object | |
{ | |
if(!object) | |
return; | |
// Find the underlying object in the array | |
WAArrayWeakPointer *ptr = [self weakPointerForObject:object]; | |
if(ptr) { | |
[self removeObject:ptr]; | |
[self cleanWeakObjects]; | |
} | |
} | |
/// | |
/// Cleans the collection of any lost weak objects | |
/// | |
-(void)cleanWeakObjects | |
{ | |
// Build a list of dead references | |
NSMutableArray *toBeRemoved = [[NSMutableArray alloc] init]; | |
for (WAArrayWeakPointer *ptr in self) { | |
if(ptr && !ptr.object) { | |
[toBeRemoved addObject:ptr]; | |
} | |
} | |
// Remove the dead references from the collection | |
for(WAArrayWeakPointer *ptr in toBeRemoved) { | |
[self removeObject:ptr]; | |
} | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment