What's the harm of retain self in block?(Objective-C, GCD) - objective-c

In many guide about how to use blocks and GCD, one tip is always mentioned : do not retain self in block.
The detail is when defining a block, if you reference self or a ivar of self, then self is retained by the block. So the work around is to use __block modifier to get a weakSelf or weakIvar.
But what's the harm of not doing that? If the block retains self, it should release self when the block is finished(Am I right about this?). So ultimately the reference count of self is balanced. I know if self retains the block and the block retains self, it would be a retain cycle.Neither the block and self will be deallocated. But if using GCD, self don't retain the block, why not let the block retain self?

There is no harm in retaining self unless the block stays around. If you are using GCD to execute the block and then it is removed then that is fine. It is only a problem if self has a reference to the block that it keeps around (i.e self.someBlock = ^{self.x = 2;}) because then you have a retain cycle.
Personally I like the block retaining self (if used) in GCD as you have no real control over when the block executes and it cannot be canceled, so it may execute after self is deallocated if it is not retained.

Related

When should we change weakSelf to strongSelf?

I know that when we use block we should use weakSelf to avoid retain cycle.But I saw there is a strongSelf in block sometimes.
What confused me are:
why must change weakSelf to strongSelf?
if we don't change weakSelf to strongSelf what terrible thing would happen?
when should we change weakSelf to strongSelf?
Hope someone can give an exact example.
Thanks in advance.
why must change weakSelf to strongSelf?
Sometimes you want your block to NOT execute if the reference to self is already nil (user dismissed the view). This is why you first use weak references. (COMMON CASE)
However, sometimes you want your block to finish executing ensuring all the things its referencing are alive, but only if "self" is still alive once the block has started. In this case you make the block convert the weak reference into strong. (RARE CASE)
if we don't change weakSelf to strongSelf what terrible thing would happen?
If the block started executing while self is alive (allowing it to begin) but gets deallocated in the middle of the processing (think of a time consuming function such as image processing), and then the block accesses a resource from self (which no longer exists) it will crash.
when should we change weakSelf to strongSelf?
Almost never. The only example I can think of is when your block absolutely needs the resources from "self" once it has begun executing.
There's a more detailed explanation in this answer:
Strong reference in the block, it will be retained?
The only reason to capture self, as a weak or strong reference, in a block is because the block uses it in some way.
When self has been captured weakly how it is used will determine when, and if, you need to make a strong copy first.
If the block is going to use the captured reference multiple times then a strong copy should always be made, this insures the reference stays alive across all the uses within the block and avoids the cost of loading a weak reference multiple times.
For example, if the block's function is dependent on whether self still exists then it would be usual to start by making a strong reference and testing it. Something along the lines of:
__weak __typeof(self)weakSelf = self;
myBlock = ^{
// make local strong reference to self
__typeof(weakSelf) strongSelf = weakSelf;
// check if self still exists and process accordingly
if (strongSelf)
{
// do whatever is needed if "self" still exists
// strongSelf will keep the object alive for the
// duration of the call
}
else
{
// do whatever, if anything, is needed if "self" no longer exists
}
});
However if the block's operation only optionally requires the use of the object referenced by self then a strong copy may never be made.
HTH
In any case you need the "self" after the callback return - it is never wrong to turn weak self to strong self, in worst case - just extra code. but the opposite is not true.
here is a very simple example where you indeed need a strong ref.
__weak typeof(self) weakSelf = self;
[self.bgQueue1 addOperationWithBlock:^{
[weakSelf doSomeMagic:weakSelf.importentArr arg:number];
if (weakSelf.importentArr.count == 10){
//we will have crash(or other unpredictable results) if weakSelf will turns to nil
[DataBaseClass save:weakSelf.importentArr];
}
}];

Copying a changing object to inside a block, so the block has the correct value

I have this loop that has this NSDictionary. Every turn, this NSDictionary is created with new values. The problem is that this loop fires an async block to be executed. Something like:
for (int i=0; i<10; i++) {
NSDictionary *aDict = [self fillDictWithCurrentValues];
dispatch_async(dispatch_get_main_queue(), ^{
executeBlock(aDict);
});
}
My problem is this. I want this block to execute with the dictionary passed to it but because the loop will execute faster, it will go out of scope when executeBlock runs. So, two questions:
I suspect every block will hold a reference to its correspondent aDict, so they will not crash even if they execute when the caller is out of scope, right?
aDict is a strong reference. Do I need to create a __weak version before calling the dispatch_async and a __strong reference inside the dispatch_async so there is no retain cycle?
You ask:
I suspect every block will hold a reference to its corresponding aDict, so they will not crash even if they execute when the caller is out of scope, right?
It will keep strong reference while the block runs, so you don't have to worry about it being deallocated on you.
That having been said, there is a question of what fillDictWithCurrentValues does. If it's creating a new dictionary each time, you're fine. But if it's returning some reference to some dictionary that is shared, this can be problematic. It just depends upon what this method is doing.
aDict is a strong reference. Do I need to create a __weak version before calling the dispatch_async and a __strong reference inside the dispatch_async so there is no retain cycle?
There's no strong reference cycle because when dispatch_async is done running the block, the block will be released.
You might still use the weakSelf pattern if (a) there's a possibility that self might be deallocated before the closures are done running; and (b) you think it's important that the closures don't prevent that from happening. But usually, when dispatching updates back to the main queue (which you only do with very fast routines), you don't worry about it.

Do we need to use weak self in blocks in Objective-C?

I noticed Apple's documentation saying we need to avoid strong reference cycles when capturing self.
The block in the example is a property of self.
But what if I put a block as a local variable in a dispatch_async statement?
In this case, it will not create a retain cycle even if I directly call a method of self, right?
Is the following code generating weakSelf required in this article?
// your code
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf doThis];
[strongSelf doThat];
[Manager.sharedInstance updateSuccessCount];
}
});
// more code
In the example given, using dispatch_async, there would be no retain cycle, so it would be safe to capture self strongly here. The only difference would be that if self were released by everything else between when this dispatch_async was called and when the block actually ran, it would slightly delay the actual deallocation of self for that brief time, and could affect which thread the deallocation actually occurs on as well. But in general there's no harm in doing it either way when using dispatch_async.
One case where you may want to do it the way your example is written above is if the code run in the block is somewhat expensive and would only want to be done if absolutely necessary, and that it's unnecessary if self had already been released by everything else.
Another case may be if self uses a large amount of memory and gets deallocated normally right before something else starts consuming a lot of memory. In that case you may not want those two instances to be allocated at the same time.

Is it safe to pass local variables as method parameters inside of a block?

I know blocks in Obj-C allow you to reference local variables, which is nice. But can we safely pass local variables to another method from inside of a block?
I know referencing self can be dangerous from inside blocks, but does this extend to any other variables.
Example:
-(void)methodTakesObject(ObjectA *)object {
ObjectB *b = object.b;
__weak MyObject *weakSelf = self;
[b doInBackground:^(NSArray *results) {
[weakSelf doSomethingElseWith:results andWith:object andEvenWith:b];
}
}
There are three "types" of local variables here. the results from the block, the ObjectB created inside the method, and an ObjectA which was passed to the method to start.
Should I be concerned about using any of these variables, and indeed is there any difference/concerns between how these variables are treated from within the block
In fact, it makes no difference no matter what variables are involved.
The concern with a retain cycle is if an object holds a strong reference to a block that it isn't expected to release until it is deallocated while the block holds a strong reference to that same object. That's not happening here.
A method called -doInBackground: seems like it will run the block (starting immediately-ish) and then release the block when it finishes. So, there's no prospect of the block being kept around as long as some other object exists, thus there's no prospect of it keeping that other object around forever.
You don't even need to use the weak-self convention to avoid a retain cycle here. You would only use it in the unlikely case that you really want to allow self to sometimes be deallocated before the block calls its method. More likely, you should just use a normal, strong reference to self because it's normal and/or desirable for self to live long enough for the block to execute.
If you are worried about retain cycle, #ken gave you the perfect answer. As for the concerns about variables:
object is retained from the method that called
methodTakesObject: so you don't have to worry about it. (if it isn't nil, tho).
b is also retained by you, the reference count is likely 2 or
more, so you also don't have to worry about it.
In other words, you are safe.

Is it necessary to use __strong in a completion block with __weak? [duplicate]

I think I understand strong and weak keywords well, but I don't understand how it's used in the code below. This code is from SDWebImage by Olivier Poitrey available on github. I understand strong and weak keywords as is described here: Explanation of strong and weak storage in iOS5
The code below uses __weak and __strong keywords in a way that is curious to me. It is not a child-parent relationship or delegate pattern as I am used to seeing weak used. However, I'm sure that this is a pattern that is used often, as I've seen it before in other code. It sets a __weak reference before a block that runs on another thread. Then, within the block, it sets the weak reference to a strong reference.
I am certain that this good and elegant code, so I'm trying to understand it. If "self" ceases to exist before the block runs, the weak self reference will zero out. When the block runs, the strong reference will be set to zero as well. Therefore, it will know to kill the rest of the operation since self doesn't exist anymore. Did I get this right?
Now, what would happen if we didn't use __weak and __strong keywords? What if we just checked inside the block whether self == nil. Would "self" never be nil since the block copies the entire tree?
Can someone help demystify this awesome piece of code? Can someone verify or repudiate my hypotheses?
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock;
{
[self cancelCurrentImageLoad];
self.image = placeholder;
if (url)
{
__weak UIImageView *wself = self;
id<SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished)
{
__strong UIImageView *sself = wself;
if (!sself) return;
if (image)
{
sself.image = image;
[sself setNeedsLayout];
}
if (completedBlock && finished)
{
completedBlock(image, error, cacheType);
}
}];
objc_setAssociatedObject(self, &operationKey, operation, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
}
The downloadWithUrl: method might take a long time. In that time, the user might decide to navigate away, eliminating the need for the SDWebImage object. To facilitate early cleanup of the object, the outer self reference is weak. This way, downloadWithUrl won't prevent the SDWebImage from being deallocated.
Of course, if you actually want to work with self, you need a strong reference. So, the on-completion block of downloadWithUrl grabs a strong reference to self. If the object goes away in this time, sself will be nil. Otherwise, it will be a valid strong reference, indicating that the SDWebImage object is still around, and the object will finish its work at this time.
I am certain that this good and elegant code, so I'm trying to understand it. If "self" ceases to exist before the block runs, the weak self reference will zero out. When the block runs, the strong reference will be set to zero as well. Therefore, it will know to kill the rest of the operation since self doesn't exist anymore. Did I get this right?
Nope, you're over thinking this quite a bit. The __weak storage qualifier is just that: a qualifier. Objects that are __weak are explicitly unretained, but they aren't just automatically set to nil if assigned from a strong variable. In fact, that would defeat the purpose of a weak variable!
Now, what would happen if we didn't use __weak and __strong keywords? What if we just checked inside the block whether self == nil. Would "self" never be nil since the block copies the entire tree?
The checking is actually unnecessary because the runtime resolves messages to nil to nil (nevertheless, it may be important to the implementation later on, who knows). You are spot on with this one: without that little "weak to strong" dance there, then self would be retained by the block, with the potential to create a pretty nasty retain cycle. Which is where I can start tying this all together:
Because we don't want the block to retain our variable, but we also want it to be strong inside the scope of the block so nothing weird happens, self is assigned to a weak pointer. When the block happens upon our weak pointer, it isn't allowed to retain it, so self's reference count stays the same, then once inside the block, we go right back to a strong self variable so the weak one is released, and we don't have to worry about it any more. Practically, this means we have a solid guarantee that self is either a value or nil throughout the entire execution of the block. Pretty neat, huh?