In a class, I've declared a thread like:
#property (nonatomic, strong) dispatch_queue_t databaseQueue;
and then I perform an operation this thread like
dispatch_async(self.databaseQueue, ^{
[self.dao deleteRetries];
});
Can this potentially create a retain cycle?
AND
the current class holds a strong reference to viewControllerToDismiss and there is a code which looks like:
[viewControllerToDismiss dismissViewControllerAnimated:shouldAnimateDismiss completion:^{
[self performSomeAction];
}
is this a retain cycle?
It is merely a strong reference to self that is eliminated automatically when the block finishes running and GCD releases the block. Note, this is a strong reference between the queue object itself, the block, and self, but not to databaseQueue. E.g. even if databaseQueue was some local reference that had fallen out of scope after you dispatched but before it ran, you'd still have a strong reference between the queue object, the block, and self.
If you don't want that strong reference at all, use weakSelf pattern:
typeof(self) __weak weakSelf = self;
dispatch_async(self.databaseQueue, ^{
[weakSelf.dao deleteRetries];
});
You asked:
Please could you elaborate more on "Note, this is a strong reference between the queue object itself, the block, and self, but not to databaseQueue"?
Consider:
- (void)runManyTasks {
dispatch_queue_t queue = dispatch_queue_create("com.domain.app.foo", 0);
for (NSInteger i = 0; i < 10; i++) {
dispatch_async(queue, ^{
[self doSomething];
});
}
}
- (void)doSomething {
[NSThread sleepForTimeInterval:1];
}
Even though I have no references in my code to that local variable, queue, after runManyTasks finishes, if I call runManyTasks, GCD will keep its own strong reference to the actual underlying queue object until all tasks finish, and the queue will keep copies of those blocks until they finish running, and those blocks will maintain a strong reference to self until GCD finishes with all of them (roughly 10 seconds, in this example).
You go on to edit your question and ask:
the current class holds a strong reference to viewControllerToDismiss and there is a code which looks like:
[viewControllerToDismiss dismissViewControllerAnimated:shouldAnimateDismiss completion:^{
[self performSomeAction];
}
is this a retain cycle?
For all practical considerations, no. That block is released as soon as the dismissal animation is done, so you generally wouldn't complicate your code with weakSelf pattern here. In fact, that view controller isn't dismissed until the animation finishes, anyway, so there's absolutely nothing gained from weakSelf pattern (other than making code more convoluted).
First, you have not declared a thread. It’s a queue, that’s something different. (Fortunately, as working directly with threads is a pain.)
You are dispatching a block into the queue. The block retains self and the queue retains the block, which means you do have a retain cycle, since the queue, being a strong property, is retained by self:
self -> queue -> block -> self -> queue -> …
BUT the block should be short-lived, judging by the API. When the block is finished, it will get released from the queue, breaking the retain cycle. So I would not worry about a case like this.
Using self directly in blocks will create strong retain cycle.
To avoid retain cycle, please check below code
__weak YourViewController *weakSelf = self;
dispatch_async(self.databaseQueue, ^{
if (weakSelf){
YourViewController *strongSelf = weakSelf;
[strongSelf.dao deleteRetries];
}
});
For more info visit this link Working with blocks
Related
I'm trying to correctly avoid retain cycles with blocks in Objective C, and am not sure about having nested blocks.
If I write a simple block like this:
[self doSomethingWithBlock:^{
[self doSomethingElse];
}];
The compiler catches and warns me that this could cause retain cycles. I change it as follows to avoid the cycle:
__weak __typeof(self)weakSelf = self;
[self doSomethingWithBlock:^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
[strongSelf doSomethingElse];
}];
When I write something like this:
[self doSomethingWithBlock:^(MyObject* object){
[object doSomethingElseWithBlock:^{
[self doYetAnotherThing];
}];
}];
The compiler is happy, but I'm not convinced that it's safe. Even though there is an intermediary object in between, it still looks conceptually the same as above, but now it's a cycle with 3 retains.
Should it be like this instead?
[self doSomethingWithBlock:^(MyObject* object){
__weak __typeof(self)weakSelf = self;
[object doSomethingElseWithBlock:^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
[strongSelf doYetAnotherThing];
}];
}];
Or like this?
__weak __typeof(self)weakSelf = self;
[self doSomethingWithBlock:^(MyObject* object){
[object doSomethingElseWithBlock:^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
[strongSelf doYetAnotherThing];
}];
}];
In this situation, you are not worried about cyclic references. What you are worried about is a situation where the object self isn't actually needed anymore, but using self inside a nested block would keep it unnecessarily alive. For example, if you have a view controller that should go away when the view is removed by the screen, but you download an image that you would like to display in the controllers view. If the image arrives long after the view is already gone, you don't want the view controller alive anymore.
Best is
__weak typeof (self) weakSelf = self;
before calling the outermost method. Then within every block that ought to use self, you add
typeof (self) strongSelf = weakSelf;
and use strongSelf within that block. Depending on the situation, you might want to check that strongSelf isn't nil at that point, but sending messages to strongSelf when it is nil has no effect, so if all you do is sending messages and getting or setting properties, then a check for nil is not necessary.
What happens if you don't do this? The difference will be that self may be kept alive unnecessarily into the innermost block, if you use self everywhere (or just in the innermost block).
You should not capture something weakly just because you get a warning from the compiler; the compiler warning is just guessing; it doesn't know how the methods you call make the references. You should only do this if you understand the architecture of the references and determine that there is a cycle and determine that capturing a weak reference instead still preserves the intended behavior. You haven't shown us the code of -doSomethingWithBlock:. It would only create a retain cycle if inside that method it assigns the block to a property or instance variable of self. Does it do that or not? If not, then there is no retain cycle, and there is no point to the outer block capturing self weakly.
Assuming that the outer block capturing self weakly is right, the examples where the outer block captures self strongly are out of the question. The remaining questions would be whether the inner block should capture self (or whatever version of self, e.g. strongSelf, is appropriate) strongly. In other words, whether you would do something like this:
__weak __typeof(self) weakSelf = self;
[self doSomethingWithBlock:^(MyObject* object){
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[object doSomethingElseWithBlock:^{
[strongSelf doYetAnotherThing];
}];
}
}];
or something like this:
__weak __typeof(self) weakSelf = self;
[self doSomethingWithBlock:^(MyObject* object){
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[object doSomethingElseWithBlock:^{
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf doYetAnotherThing];
}
}];
}
}];
Again, the main issue to determine is whether there is a retain cycle if the inner block captures self strongly. There would only be a retain cycle if [object doSomethingElseWithBlock:... somehow assigns the block to a property or instance variable of self. But how could it? The method is called on object, not self. The method does not get self in any way. Unless there is something complicated going on, the method is not going to assign to a property or instance variable of self, so it is unlikely to create a retain cycle. This means that the inner block capturing self weakly is not necessary to prevent a retain cycle.
But whether the inner block captures self weakly or strongly could affect the behavior. Namely, if the inner block captures self weakly, self could be deallocated by the time the block is run, in which case [strongSelf doYetAnotherThing]; will not be executed, whereas if the inner block captured self strongly, it would keep self alive and [strongSelf doYetAnotherThing]; would be executed. So it depends on what -doYetAnotherThing does. If it performs some UI operation on self which is a UI view or something, then whether you perform it on a view that is no longer displayed doesn't make a difference. But if it for example sends something to the network or something, then whether or not it is executed can make a big difference.
Xcode 8 beta 4 underlines the self keyword, and warns of a possible retain cycle for having used it inside the block.
Per Apple Developer Connection's Programming in Objective-C (Working with Blocks):
Avoid Strong Reference Cycles when Capturing self If you need to
capture self in a block, such as when defining a callback block, it’s
important to consider the memory management implications.
Blocks maintain strong references to any captured objects, including
self, which means that it’s easy to end up with a strong reference
cycle if, for example, an object maintains a copy property for a block
that captures self:
#interface XYZBlockKeeper : NSObject
#property (copy) void (^block)(void);
#end
#implementation XYZBlockKeeper
- (void)configureBlock {
self.block = ^{
[self doSomething]; // capturing a strong reference to self
// creates a strong reference cycle
};
}
...
#end
The compiler will warn you for a simple example like this, but a more
complex example might involve multiple strong references between
objects to create the cycle, making it more difficult to diagnose.
To avoid this problem, it’s best practice to capture a weak reference
to self, like this:
- (void)configureBlock {
XYZBlockKeeper * __weak weakSelf = self;
self.block = ^{
[weakSelf doSomething]; // capture the weak reference
// to avoid the reference cycle
}
}
By capturing the weak pointer to self, the block won’t maintain a
strong relationship back to the XYZBlockKeeper object. If that object
is deallocated before the block is called, the weakSelf pointer will
simply be set to nil.
This site reportedly provides a means for making the self keyword weak whenever it's used inside a block; it also provides instructions for returning a weak self or class object formerly strong, strong again:
https://coderwall.com/p/vaj4tg/making-all-self-references-in-blocks-weak-by-default
Look at the answer for this question.
I'd do this
__weak typeof (self) weakSelf = self;
[self doSomethingWithBlock:^(MyObject* object){
[object doSomethingElseWithBlock:^{
[weakSelf doYetAnotherThing];
}];
}];
I'm working on doing network requests in my app and am using NSBlockOperations in an NSOperationQueue to do this asynchronously. However, I want to be able to cancel these operations if the view controller that called them is deallocated (has been popped off the navigation stack).
This is a simplified version of what I have:
NSArray *posts;
__weak DataController *weakSelf = self;
NSBlockOperation *fetchPostsOperation = [NSBlockOperation blockOperationWithBlock:^{
DataController *strongSelf = weakSelf;
NSDictionary *response = [weakSelf refreshPostsInPart:PartFirst];
posts = [response objectForKey:#"posts"];
}];
[self.queue addOperation:fetchPostsOperation];
In the refreshPostsInPart: method of DataController I make repeated network requests for paginated data from App.net using a while loop. At each iteration of the loop I check a property of DataController self.isCancelled (of type BOOL), if it is NO I keep making requests.
In my dealloc method of DataController I set this property to be YES so that on the next iteration of the while loop I will stop making requests. In essence, I'm implementing a poor mans cancelAllOperations while using NSBlockOperation.
Question: When setting self.isCancelled to NO in my dealloc method, am I also setting self.isCancelled for the strongSelf reference that is being used in the block?
self, weakSelf, and strongSelf all refer to the same object in memory. That means that if you send a message to self in dealloc (which you do by setting that property), weakSelf and strongSelf also "know" about this updated property. So, yes, you are setting self.isCancelled (more than likely the actual property's name is self.cancelled and its getter is isCancelled) on strongSelf as well.
I have an IOS project (ARC disabled) which has several view controllers. One particular controller initialises a member object of type MyClass, however when the view controller is dismissed, I'm calling a cleanup method for the object which uses a thread (using dispatch-async) to make some time consuming operations and then when these operations are done im executing a [self release] on the main queue for the object. Is this a good practise, will it cause any errors? Below is a similar example to what im doing:
#implementation ViewController
- (void)viewDidLoad
{
myObj = [[MyClass alloc] init];
}
-(void)viewWillDisappear
{
[myObj cleanup];
}
#end
//myClass
#implementation MyClass
- (void)cleanup()
{
dispatch_queue_t myQueue = dispatch_queue_create ("MyClassDeallocQueue", NULL);
dispatch_async(myQueue, ^{
//time consuming operations
dispatch_async(dispatch_get_main_queue(), ^{
[self release];
});
});
}
#end
Is this a good practise, will it cause any errors?
Currently, your code has an unbalanced retain/release. That is definitely an error (over release).
"Is it good practice?" - well, I don't know what you are trying to accomplish. But if your goal is to keep self alive, until after the block is executed, it is already accomplished purely through the fact that self will be captured. So, strictly a release is not needed.
However, if you NOT explicitly release self on the main thread, you introduce a subtle bug: it might happen that the block has the last reference to self, and since it may execute on some arbitrary thread, it will release self on this non-main thread. And this is forbidden: UIKit methods (including dealloc) MUST be called on the main thread!
Thus, it might make sense:
[self retain];
dispatch_async(myQueue, ^{
// time consuming operation, which captures `self`
[self doSomething];
...
// ensure that `dealloc` will be executed on the main thread, if
// last reference is held by the block:
dispatch_async(dispatch_get_main_queue(), ^{
[self release];
});
});
or shorter:
dispatch_async(myQueue, ^{
// time consuming operation, which captures `self`
[self doSomething];
...
// ensure that `dealloc` will be executed on the main thread, if
// last reference is held by the block:
dispatch_async(dispatch_get_main_queue(), ^{
[self self];
});
});
Edit:
It's an interesting question, whether the "short" version is actually tread-safe or has a race:
Suppose, self will be released in the block executed on myQueue, as the effect of capturing self before it will be retained in the same bock as an effect of capturing self for the block executed on the main queue. Then, we have an issue. Comments appreciated.
Suppose I already create a weak self using
__weak typeof(self) weakSelf = self;
[self doABlockOperation:^{
...
}];
Inside that block, if I nest another block:
[weakSelf doAnotherBlockOperation:^{
[weakSelf doSomething];
}
will it create a retain cycle? Do I need to create another weak reference to the weakSelf?
__weak typeof(self) weakerSelf = weakSelf;
[weakSelf doAnotherBlockOperation:^{
[weakerSelf doSomething];
}
Your code will work fine: the weak reference will not cause a retain cycle as you explicitly instruct ARC not to increase the retainCount of your weak object. For best practice, however, you should create a strong reference of your object using the weak one. This won't create a retain cycle either as the strong pointer within the block will only exist until the block completes (it's only scope is the block itself).
__weak typeof(self) weakSelf = self;
[self doABlockOperation:^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
...
}
}];
It depends.
You only create a retain cycle if you actually store the block (because self points to the block, and block points to self). If you don't intend to store either of the blocks, using the strong reference to self is good enough --- block will be released first after it got executed, and then it will release it's pointer to self.
In your particular example, unless you're performing more operations which are not shown, you don't need to create any weakerWeakerEvenWeakerSelfs.
I'm trying to figure out if I do this right:
If I have one block, I'll do this:
__weak MyClass *weakSelf = self;
[self performBlock:^{ //<< Should I use self, or weakSelf here?
[weakSelf doSomething];
} afterDelay:delay];
But what happens if there's a block in a block? Would this be correct?
__weak MyClass *weakSelf = self;
[self performBlock:^{
[weakSelf doSomething];
[self performBlock:^{
[weakSelf doSomething];
} afterDelay:1.0f];
} afterDelay:delay];
Also, in the function below, do I need to use [block copy]?
- (void)performBlock:(void (^)(void))block afterDelay:(float)delay
{
if (block)
{
if (delay > 0)
{
[self performSelector:#selector(executeBlockAfterDelay:) withObject:[block copy] afterDelay:delay];
}
else
{
[self executeBlockAfterDelay:[block copy]];
}
}
}
- (void)executeBlockAfterDelay:(void(^)(void))block
{
if (block)
block();
}
In this case (below) use just strong self, because the block is copied just for those few seconds. And usually if you want the self to perform block, you want to it to stay alive until that time, so strong reference is perfectly okay.
[self performBlock:^{
[self doSomething]; // strong is OK
} afterDelay:delay];
Block inside a block? In your case those two block are just delayed one-shot blocks, so the same as above, use strong. But there are differences between blocks. If you store the block for longer time, maybe for multiple invocations you should avoid retain-cycles.
Example:
self.callback = ^{
[self doSomething]; // should use weakSelf
};
This may cause retain-cycle. In fact it depends on how the block is used. We see that the block is stored (copied) in property for later use. However, you can prevent the retain-cycles by nullifying block that will not be used any more. In this case:
self.callback(); //invoke
self.callback = nil; //release
When using ARC, you don't have to copy blocks yourself. There were bugs in early versions after blocks were added, but now the compiler under ARC knows when to copy blocks. It is clever enough to copy it in this case:
[self performSelector:#selector(executeBlockAfterDelay:) withObject:block afterDelay:delay];
Rather than implementing -performBlock:afterDelay:, just use dipatch_after(). Among other things, that's not a message delivered to an object, so there's no question of what receiver to target it at.
Actually, there's no memory management issue here at all. One typically only needs to do a "weak self" approach when an object retains a block and the block (perhaps implicitly) retains that same object. However, the object is not retaining the block. It is being retained by the framework until the -performSelector:withObject:afterDelay: fires, but that's not a retain cycle.
If there were a retain cycle, then you should not reference self in the blocks. So, your nested case is wrong in invoking a message on self rather than weakSelf.
Finally, yes, you do need [block copy] whenever you are keeping a block after execution leaves the scope of its declaration or if you pass it to non-block-specific API that does. That is, you don't need to copy a block when you pass it to, say, dispatch_async() because that's a block-aware API that knows to make its own copy as necessary. But -performSelector:withObject:afterDelay: is not block-aware. It just treats its argument as a generic object and retains it. So, you do have to copy the block when passing it to that.
One the most important thing to understand about blocks is that they capture a piece of code (including values) in an abstract entity that can be manipulated as an atomic object (keep it somewhere, pass it, copy, etc...). Actually it is implemented in a way that guarantee that by default your block will remain valid and executable safely later.
Then capturing and retaining the required dependencies inside the block is necessary.
Unfortunately, in some cases (quite often actually) the block is retained by the instance that creates it and it retains itself that instance. This is called a retain loop and makes your object and your block impossible to dealloc unless you break one of the retaining relation yourself. This can happen if you reference your block with an instance variable for example and you don't nillify it manually.
This is probably the main issue with blocks especially because sometime, you don't know that your block retains your self instance (NSAssert within your block for example). Then:
If you execute your block immediately and release it (use your block
with dispatch release it after execution) there is no risk since you
are sure your object referenced by self still exist.
But if the execution is delayed it is important to retain your object within your block. But in that case your object should not retain your block to avoid a retain loop (A retains B and B retains A). If you define and optionally reference your block in the private scope of method it is perfect.
About copy. Yes it can be safer to use copy if your block in passed as a method argument to be sure you have a clean exclusive block in this scope with a +1 retainCount. But maybe ARC already do it for you. Not sure about that. For example it performWithSelector seems to do it for free, then copy is not dangerous. Just a useless. Sometime the compiler can optimise that by removing it but it has to be checked.
I usually do this:
__unsafe_unretained __block id blockSelf = self;
and then use it in my blocks no issues.
So in your case:
__unsafe_unretained __block MyClass *blockSelf = self;
[self performBlock:^{
[weakSelf doSomething];
[self performBlock:^{
[weakSelf doSomething];
} afterDelay:1.0f];
} afterDelay:delay];
Also to make your life a tad easier - make a utilities class and put this in the header
void RunAfterDelay(NSTimeInterval delayInSeconds, dispatch_block_t block);
and then this in the .m file
void RunAfterDelay(NSTimeInterval delayInSeconds, dispatch_block_t block)
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC), dispatch_get_main_queue(), block);
}
Import the utilities into your prefix and you can go:
__unsafe_unretained __block MyClass *blockSelf = self;
RunAfterDelay(1.0f,^{
[blockSelf doSomething];
RunAfterDelay(delay,^{
[blockSelf doSomething];
})
});
I find it a bit nicer to read than the verbose default ones.
Hope this helps :)