When should we change weakSelf to strongSelf?
Asked Answered
F

3

10

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:

  1. why must change weakSelf to strongSelf?
  2. if we don't change weakSelf to strongSelf what terrible thing would happen?
  3. when should we change weakSelf to strongSelf?

Hope someone can give an exact example.

Thanks in advance.

Franciscafranciscan answered 13/7, 2017 at 2:55 Comment(1)
#11014087Bairn
I
18
  1. 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)

  1. 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.

  1. 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?

Innocence answered 13/7, 2017 at 3:25 Comment(4)
Can I say change weakSelf to strongSelf is more safe than only use weakSelf?Franciscafranciscan
Yes, as long as you check that 'self' exists at the beginning of the block. But it is a very rare case in, once you've entered the block, self disappears. (read the linked question.Innocence
"and then the block accesses a resource from self (which no longer exists) it will crash." It depends on what you mean by "access a resource from". In this case it would access it from weakSelf (not self), which will be nil when the object pointed to is deallocated. Calling a method or accessing a property (which is calling a method) on a nil pointer will not crash. Only if you directly access an instance variable using -> on weakSelf would it crash if it were nil.Disciplinant
@Disciplinant this is objective-c so yeah, sending a message to nil doesn't crash, but in many methods adding a nil will make it crash. Think of NSArray when adding a "nil" object, it crashes.Innocence
M
8

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

Matsuyama answered 13/7, 2017 at 5:44 Comment(0)
H
0

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];
        }
    }];
Hypopituitarism answered 11/12, 2019 at 20:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.