为什么带有__weak修饰符的变量会保留一个对象?

4

这是我的代码:

extern void _objc_autoreleasePoolPrint();

int main(int argc, const char * argv[])
{

    NSArray __weak *tmp = nil;

    @autoreleasepool {

        NSArray __strong *obj = [[NSArray alloc] init];

        NSLog(@"obj &: %p", obj);

        tmp = obj;

        NSLog(@"tmp &: %p", tmp);

        _objc_autoreleasePoolPrint();
    }

    NSLog(@"tmp: %@", tmp); // why not (null) ?


    return 0;
}

并且控制台输出:

    2013-05-01 22:14:32.966 SimpleConsoleObjectiveCApplicationWithARC[40660:f07] obj &: 0x7fedf9403110
2013-05-01 22:14:32.969 SimpleConsoleObjectiveCApplicationWithARC[40660:f07] tmp &: 0x7fedf9403110
objc[40660]: ##############
objc[40660]: AUTORELEASE POOLS for thread 0x7fff751af180
objc[40660]: 2 releases pending.
objc[40660]: [0x7fedf9805000]  ................  PAGE  (hot) (cold)
objc[40660]: [0x7fedf9805038]  ################  POOL 0x7fedf9805038
objc[40660]: [0x7fedf9805040]    0x7fedf9403110  __NSArrayI
objc[40660]: ##############
2013-05-01 22:14:32.971 SimpleConsoleObjectiveCApplicationWithARC[40660:f07] tmp: (
)

注意 #1

将NSArray更改为NSMutableArray,tmp变量变为nil。

extern void _objc_autoreleasePoolPrint();

int main(int argc, const char * argv[])
{

    NSMutableArray __weak *tmp = nil;

    @autoreleasepool {

        NSMutableArray __strong *obj = [[NSMutableArray alloc] init];

        NSLog(@"obj &: %p", obj);

        tmp = obj;

        NSLog(@"tmp &: %p", tmp);

        _objc_autoreleasePoolPrint();
    }

    NSLog(@"tmp: %@", tmp);


    return 0;
}

有人能解释一下为什么它是这样工作的吗?
1个回答

5

看起来[[NSArray alloc] init]返回一个空的NSArray的“共享实例”:

NSArray *a = [[NSArray alloc] init];
NSArray *b = [[NSArray alloc] init];
NSLog(@"a &: %p", a);
NSLog(@"b &: %p", b);

输出:

    a &: 0x100103110
    b &: 0x100103110

即使您的强引用obj已经消失,这个“共享实例”仍然存在,因此弱指针不会被设置为nil

显然,[[NSMutableArray alloc] init]不能返回一个共享实例。


Martin R,是的,所有的不可变类都返回“共享实例”(已经检查了NSString、NSDictionary等),但是有没有办法将这个“特性”传递呢? - AndrewShmig
2
@AndrewShmig:你想要实现什么?为什么需要弱引用变成nil? - Martin R
Martin R,我正在尝试理解为什么在变量obj离开其作用域后,__weak没有按预期工作。 - AndrewShmig
2
@AndrewShmig:如果指向的对象被销毁,那么弱指针将被设置为 nil,而不是当你的指向该对象的指针离开作用域时。NSArray 类会保持自己对共享实例的强引用,因此即使你的指针 obj 离开作用域,该对象也不会被销毁。 - Martin R

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接