NSArray слабых ссылок (__unsafe_unretained) на объекты в ARC - PullRequest
68 голосов
/ 18 февраля 2012

Мне нужно хранить слабые ссылки на объекты в NSArray, чтобы предотвратить сохранение циклов.Я не уверен в правильном синтаксисе для использования.Это правильный путь?

Foo* foo1 = [[Foo alloc] init];
Foo* foo2 = [[Foo alloc] init];

__unsafe_unretained Foo* weakFoo1 = foo1;
__unsafe_unretained Foo* weakFoo2 = foo2;

NSArray* someArray = [NSArray arrayWithObjects:weakFoo1, weakFoo2, nil];

Обратите внимание, что мне нужно поддерживать iOS 4.x , поэтому __unsafe_unretained вместо __weak.


РЕДАКТИРОВАТЬ (2015-02-18):

Для тех, кто хочет использовать истинные __weak указатели (не __unsafe_unretained), пожалуйста, проверьте этот вопрос вместо: Коллекции обнуления слабых ссылок по ARC

Ответы [ 12 ]

1 голос
/ 08 января 2013

Если вам нужно обнуление слабых ссылок, см. этот ответ для кода, который вы можете использовать для класса-оболочки.

Другие ответы на этот вопрос предлагают обертку на основе блоков и способы автоматического удаления обнуленных элементов из коллекции.

0 голосов
/ 04 ноября 2017

Я думаю, что элегантное решение - это то, что мистер Эрик Ралстон предлагает в своем хранилище Github

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

это основные шаги:

создать категорию для NSArray и NSMutableArray

в реализации создайте удобный класс со слабым свойством. Ваша категория назначит объекты этому слабому свойству.

.h

 #import <Foundation/Foundation.h>

@interface NSArray(WeakArray)

- (__weak id)weakObjectForIndex:(NSUInteger)index;
-(id<NSFastEnumeration>)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<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)

-(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
...