Как создать слабую ссылку в Objective-C?

у меня есть такая ситуация:

NSMutableArray * A = [[NSMutableArray alloc]initwithObjects:@"one",nil];
NSMutableArray * B = [[NSMutableArray alloc]initwithObjects:@"two",nil];

[A addObject:B];
[B addObject:A];

теперь вот цикл сохранения, как я могу разорвать этот цикл сохранения? (используя слабую ссылку) .... в приведенном выше примере. Спасибо

10
задан Georg Fritzsche 1 September 2010 в 13:38
поделиться

2 ответа

Я бы поставил под сомнение причину, по которой вам нужно это сделать в первую очередь, но если вы решите, что это лучшая архитектура данных, я бы использовал NSValue. Чтобы сохранить ссылку на объект (без его сохранения) в классе коллекции Foundation, вы можете использовать +[NSValue valueWithNonretainedObject:]:

NSMutableArray *a = [[NSMutableArray alloc] initwithObjects:@"one", nil];
NSMutableArray *b = [[NSMutableArray alloc] initwithObjects:@"two", nil];

[a addObject:b];
[b addObject:[NSValue valueWithNonretainedObject:a]];

. Затем, чтобы позже получить объект из NSValue , вы должны сделать это:

NSMutableArray *c = (NSMutableArray *) [[b objectAtIndex:index] nonretainedObjectValue];

Приложение

Я изменил ответ с использования +[NSValue valueWithPointer:] на +[NSValue valueWithNonretainedObject:]. , так как под ARC компилятор будет жаловаться (из-за приведения типа объекта к const void *). Хотя функционально то же самое, приведение типов и имя метода имеют больше смысла (и компилятор фактически позволит вам скомпилировать, не прибегая к хакерству).

12
ответ дан 3 December 2019 в 15:51
поделиться

Как я решил эта проблема в прошлом заключалась в использовании подкласса NSProxy для разрыва цикла. У меня будет объект, который хранит слабую ссылку на один из массивов и передает ему все сообщения, кроме сообщений управления памятью.

     ┌──── NSArray A <────┐
     │                    │
     │                    │
     v        weak        │
ACWeakProxy ┈ ┈ ┈ ┈ ┈ > NSArray B

@interface ACWeakProxy : NSProxy {
    id _object;
}

@property(assign) id object;

- (id)initWithObject:(id)object;

@end

@implementation ACWeakProxy

@synthesize object = _object;

- (id)initWithObject:(id)object {
    // no init method in superclass
    _object = object;
    return self;
}

- (BOOL)isKindOfClass:(Class)aClass {
    return [super isKindOfClass:aClass] || [_object isKindOfClass:aClass];
}

- (void)forwardInvocation:(NSInvocation *)invocation {
    [invocation setTarget:_object];
    [invocation invoke];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
    return [_object methodSignatureForSelector:sel];
}

@end

Тогда ваш код становится

NSMutableArray * A = [[NSMutableArray alloc] initwithObjects:@"one", nil];
NSMutableArray * B = [[NSMutableArray alloc] initwithObjects:@"two", nil];

[A addObject:B];
ACWeakProxy * proxy = [[ACWeakProxy alloc] initWithObject:A];
[B addObject:proxy];
[proxy release];

// will print "two"
NSLog(@"%@", [[[B objectAtIndex:1] objectAtIndex:1] objectAtIndex:0]);

Однако вы сами должны убедиться, что ваша слабая ссылка не исчезнет, ​​пока вы ее используете.

8
ответ дан 3 December 2019 в 15:51
поделиться