Strong reference in the block, it will be retained

2020-06-06 02:05发布

I discover this snippet code from company's document:

__weak __typeof(self)weakSelf = self;
dispatch_async(dispatch_get_main_queue(),
^{
      __strong __typeof(weakSelf)strongSelf = weakSelf; 
      // Do stuff
});

It's will be retained ?

3条回答
▲ chillily
2楼-- · 2020-06-06 02:23

If you use this:

__weak __typeof(self)weakSelf = self;
dispatch_async(dispatch_get_main_queue(),
^{ 
    // Do stuff
});

Self may get deallocated while the block is being executed. So we had better to convert the weakSelf to strongSelf to ensure that self stays in memory until the block finishes execution.

After your use of __strong __typeof(weakSelf)strongSelf = weakSelf, self will refer to local, stack variables. So It's will not be retained.

查看更多
一夜七次
3楼-- · 2020-06-06 02:30

The weak copy outside the block is enough.

__weak __typeof(self)weakSelf = self;
dispatch_async(dispatch_get_main_queue(),
^{
      // silliness: __strong __typeof(weakSelf)strongSelf = weakSelf; 
      // Do stuff with weakSelf here
});

In fact, this is okay too:

dispatch_async(dispatch_get_main_queue(),
^{
    // self self self, go ahead and mention self here
});

The thing one must not do is copy that block someplace, and mention that someplace in the block.

@property (nonatomic, strong) void (^myBlock)(void);

self.myBlock = ^void(void) {
    // don't mention self here!
};

The idea is that blocks retain the objects they mention, and we're trying to avoid cycles, so object -> block -> another_object is fine, but object -> block -> another_object -> any amount of indirection -> object is a cycle, and that's bad.

Cycles are bad because an object can't be deallocated if it's retained elsewhere, and so the things it retains can't be deallocated. If two things retain each other, then they're both stuck, unable to be deallocated because each is retained by something.

EDIT what I misunderstood until today is that the strong copy of the weak var isn't always silly. It can be relevant, but the case where it makes sense is highly qualified).

查看更多
干净又极端
4楼-- · 2020-06-06 02:33

There are two reasons to capture weak references within a block.

  1. avoid retain cycles

  2. create no-op situations.

The former has been discussed ad-nauseum. The second is more interesting.

Example

The block in question is a completion handler for an image download. When the download is complete, it is to be displayed in an image view.

It doesn't need to do anything if the image view has already been deallocated (say the user has switched to a new view). There is no danger of a retain cycle, because the image view has no reference to the block. However, capturing a weak reference allows the image view to be deallocated before the block executes. Thus, if the user switches views before the image is downloaded, the block ends up doing nothing because its weak reference has already been niled. It also doesn't matter if the image view is deallocated part way through the block's execution, because it just turns operations on the image view into no-ops, instead of turning the entire block into a no-op.

Sometimes, however, the block wants the no-op behavior, but only if the reference was already nil when it began (or reached a certain point in the code path). If, at the time the block executes, the object is live, the block has to execute in its entirety. It can't stop half-way through because the object is deallocated on some other thread.

Example

The purpose of the completion block is to add a caption, defined by a string, to the image. If the string has been deallocated already, no caption is to be added. However, if the string is still live when post-processing begins, it must remain live to avoid trying to create an attributed string with a nil reference, because that leads to a crash.

In this scenario, it would be proper to capture the string with a weak reference, so it can be deallocated by some other thread (leading to no caption). However, before the string is used within the block, it must be captured strongly to avoid a crash when creating the attributed string.

查看更多
登录 后发表回答