NSArray of weak references (__unsafe_unretained) to objects under ARC

前端 未结 12 747
南旧
南旧 2020-11-27 11:26

I need to store weak references to objects in an NSArray, in order to prevent retain cycles. I\'m not sure of the proper syntax to use. Is this the correct way?



        
12条回答
  •  猫巷女王i
    2020-11-27 12:31

    I think an elegant solution is what Mr. Erik Ralston propose on his Github repository

    https://gist.github.com/eralston/8010285

    this are the essential steps:

    create a category for NSArray and NSMutableArray

    in the implementation create a convenience class with a weak property. Your category will assign the objects to this weak property.

    .h

     #import 
    
    @interface NSArray(WeakArray)
    
    - (__weak id)weakObjectForIndex:(NSUInteger)index;
    -(id)weakObjectsEnumerator;
    
    @end
    
    @interface NSMutableArray (FRSWeakArray)
    
    -(void)addWeakObject:(id)object;
    -(void)removeWeakObject:(id)object;
    
    -(void)cleanWeakObjects;
    
    @end
    

    .m

    #import "NSArray+WeakArray.h"
    
    @interface WAArrayWeakPointer : NSObject
    @property (nonatomic, weak) NSObject *object;
    @end
    
    @implementation WAArrayWeakPointer
    @end
    
    @implementation NSArray (WeakArray)
    
    
    -(__weak id)weakObjectForIndex:(NSUInteger)index
    {
        WAArrayWeakPointer *ptr = [self objectAtIndex:index];
        return ptr.object;
    }
    
    -(WAArrayWeakPointer *)weakPointerForObject:(id)object
    {
        for (WAArrayWeakPointer *ptr in self) {
            if(ptr) {
                if(ptr.object == object) {
                    return ptr;
                }
            }
        }
    
        return nil;
    }
    
    -(id)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)
    
    -(void)addWeakObject:(id)object
    {
        if(!object)
            return;
    
        WAArrayWeakPointer *ptr = [[WAArrayWeakPointer alloc] init];
        ptr.object = object;
        [self addObject:ptr];
    
        [self cleanWeakObjects];
    }
    
    -(void)removeWeakObject:(id)object
    {
        if(!object)
            return;
    
        WAArrayWeakPointer *ptr = [self weakPointerForObject:object];
    
        if(ptr) {
    
            [self removeObject:ptr];
    
            [self cleanWeakObjects];
        }
    }
    
    -(void)cleanWeakObjects
    {
    
        NSMutableArray *toBeRemoved = [[NSMutableArray alloc] init];
        for (WAArrayWeakPointer *ptr in self) {
            if(ptr && !ptr.object) {
                [toBeRemoved addObject:ptr];
            }
        }
    
        for(WAArrayWeakPointer *ptr in toBeRemoved) {
            [self removeObject:ptr];
        }
    }
    
    @end
    

提交回复
热议问题