문제

I would like to return an array whose contents were set during a dispatch_sync block.

The code I've typically seen is something like this:

-(NSArray *)getSomeLockedList {

    __block NSArray *resultList;

    dispatch_sync(myQueue, ^{   
       // copy contents of my ivar NSMutableArray into return variable  
       resultList = [ivarContentList copy]; 
    });

    // add auto-release since a 'copy' was done within block
    return [resultList autorelease]; 
}

If I'm not doing a copy of a full array but instead want to add one by one, can I skip the 'autorelease' on the return value?

-(NSArray *)getSomeLockedList {

    __block NSArray *someResultKeys; // is it ever safe to do the alloc here?

    dispatch_sync(myQueue, ^{       
       someResultKeys = [NSMutableArray array];

    for (id entry in ivarContentList) {

          // do some work on entry instance
          [someResultKeys addObject:entry];     
       }        
    });

    return someResultKeys; // autorelease not necessary?
}

Is the [NSMutableArray array] allocation safe within the dispatch_sync block for continued use of the result after the stack is completed for this method?

도움이 되었습니까?

해결책

No, this is not safe. The problem is that when you dispatch onto the queue, any objects that are autoreleased on that queue will get collected when that queue's NSAutoreleasePool drains. You have no control over when this will be. The appropriate way to think about this is to always assume that the autorelease pool will drain the moment your block finishes executing on the queue.

The correct way to handle this in your case is to use

someResultKeys = [[NSMutableArray alloc] init];

in the queue and then call [someResultKeys autorelease] after the dispatch_sync.

다른 팁

This is done much easier avoiding a __block variable by just writing

NSMutableArray* someResultKeys = [NSMutableArray array];

outside the block. However, I wonder about the dispatch_sync. You know that dispatch_sync will wait until the block finishes executing? (And in case of a serial queue, that means all blocks before it have finished executing as well). Is there a good reason why you don't call the code directly?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top