Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSHashTable retaining weak reference

So, apple's documentation for [NSHashTable weakObjectsHashTable] states:

Returns a new hash table for storing weak references to its contents.

So, when I run the following code...

NSHashTable *hashTable = [NSHashTable weakObjectsHashTable];
ABC *object = [[ABC alloc] init];
[hashTable addObject:object];
NSLog(@"%@", [hashTable anyObject]);
object = nil;
NSLog(@"%@", [hashTable anyObject]);

The output is:

2017-09-18 12:57:02.801 Test2[6912:640614] <ABC: 0x608000014eb0>
2017-09-18 12:57:02.801 Test2[6912:640614] <ABC: 0x608000014eb0>
2017-09-18 12:57:02.803 Test2[6912:640614] dealloc // (dealloc of ABC)

It looks like calling NSLog(@"%@", [hashTable anyObject]); is retaining the object.

If I call,

NSHashTable *hashTable = [NSHashTable weakObjectsHashTable];
ABC *object = [[ABC alloc] init];
[hashTable addObject:object];
//NSLog(@"%@", [hashTable anyObject]);
object = nil;
NSLog(@"%@", [hashTable anyObject]);

The ouput is as expected:

2017-09-18 13:00:23.949 Test2[6936:645459] dealloc
2017-09-18 13:00:23.949 Test2[6936:645459] (null)

Can someone tell me where my misunderstanding is?

like image 881
joelliusp Avatar asked Sep 18 '17 06:09

joelliusp


1 Answers

You don't even have to call NSLog — just doing [hashTable anyObject] is enough to make the object stick around. The reason seems to be that anyObject returns an autoreleased reference, which does not get release:d until some point in the future. Wrap the whole thing in an @autorelease block, and I believe it will work as expected.

Generally speaking, it is dangerous to make assumptions about exactly when an ARC:ed object will be released, because there is lots of magic like this going on.

like image 170
Ture Pålsson Avatar answered Oct 09 '22 20:10

Ture Pålsson