I have some piece of code:
//in the interface file
//...
NSMutableSet * someSet;
//...
//
//in the implementation file
//-(id)init {
if(self = [super self])
{
someSet = [[NSMutableSet alloc] init];
}
return self;
}
-(void)someFunc
{
NSLog(@"someSet count: %lu", [someSet count]); //always shows some number
array = ... //getting array from another function
for(SomeObject * obj in array)
{
NSSomeOperation * op = [[NSSomeOperation alloc] initWithValue:[obj someValue]];
//start operation
[someSet addObject:[obj someValue]];
}
}
//this function is called from another thread (from operation) through notification
//
-(void)someAnotherFunc
{
@synchronized(self)
{
int size = [someSet count]; //HERE size = 0, but it must be some count
NSLog(@"someSet: %@", someSet); // it outputs: "someSet: {()}"
NSLog(@"someSet count: %lu", [someSet count]); // it outputs: "someSet count: (null)"
}
}
The problem is, that size = 0 in someAnotherFunc, but it must be some count. And I know, it’s because someAnotherFunc is called from another thread, and in that thread someSet = nil.
I’ve tried performSelectorOnMainThread but it doesn’t help.
UPDATE:
I’ve debugged this, I’ve called twice someFunc, and someSet is valid object during these calls, and have some count of objects. I’ve logged count in someFunc – and outputs valid count of objects.
It only occurs when is ARC enabled, before ARC was enabled – everything was fine.
It seems it is some security from threads or ARC, to prevent to use data from different threads. Maybe I’m not right, but I don’t understand why it occurs.
During execution of this piece of code someSet is not directly assigned to nil. And it is not deallocated.
Does anyone know how to access object someSet from another thread? How to get valid count of objects in someSet?
There is nothing thread related wrong with that code (other than that you are going to run into a slew of unrelated problems by trying to do threading in this fashion).
Somewhere,
someSetis being set to nil before the other thread’s code is run. You say this only happens with ARC enabled? Then that is most likely because you don’t have a strong reference to whatever object encapsulates that code; i.e. the object is being deallocated because the compiler has determined it is no longer being used.This is most likely because your code that handles the notification is not set up to retain the observer — to keep a reference to the observer — around. Stick a reference to the observer in a global variable, directly or indirectly.
Note that the
@synchronize()in that code is likely nonsense or, if you really do have multiple threads that might be firing the notification, indicative of an architectural issue.Note also that
NSLog(@"someSet count: %@", [someSet count]); // it outputs: "someSet count: (null)"will crash ifsomeSetwere ever properly set.