Reputation: 199
I was reading this: does dispatch_async copy internal blocks
and I want to know how to get dispatch-async to nil out the block it copied onto the heap so that the block can be garbage collected.
Ok, so on the local stack, I create my block:
MyBlock aBlock = ^{
for (int i = 0; i < 10; i++) {
NSLog(@"holder is: %p, holder.block is %p", holder, holder.block);
sleep(1);
}
};
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, aBlock);
sleep(2); // give the queue some time to start executing the block
The block keeps executing simply because it is the block on the heap that is copied by dispatch_async. This is all expected behavior.
So my question is....is there a way to explicitly make this block on the heap be destroyed ?
Or will ARC memory manage that block for me from the heap when the dispatch_async has finished executing, and I personally can't do anything about it ?
Thank you!
Upvotes: 0
Views: 350
Reputation: 122439
For your updated question, you don't need to nil
anything. The block on the heap is just like any other reference counted object. Your scope has a strong reference to it for the duration of the scope of the variable aBlock
. And the asynchronous dispatch mechanism holds a strong reference to it until it has executed. When there are no strong references to it anymore, it is deallocated.
Upvotes: 0
Reputation: 119031
If you want to be able to cancel the loop you need to put a check inside and break out when the condition isn't met. That could be that your container object is now nil, or it could be the result of some method call. Just be sure that you aren't retaining or influencing the test you add by testing for it...
Upvotes: 0
Reputation: 752
you can add a BOOL property to the class BlockHolder for example :
@property (nonatomic, assign, getter = isCancelled) BOOL cancelled;
and inside the block add a test to check if the block is cancelled or not like this :
__block BlockHolder * holder = [[BlockHolder alloc] init];
MyBlock aBlock = ^{
for (int i = 0; i < 10; i++) {
if(holder.isCancelled) return;
NSLog(@"holder is: %p, holder.block is %p", holder, holder.block);
sleep(1);
}
};
and if you want to cancel the block you can set the value of cancelled to YES. I hope it will help you
Upvotes: 0