Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does clang capture ARC modifiers with __typeof?

It is known that a block may induce a retain cycle if the block implicitly retains an object that also retains the block. Example:

self.block = ^{
  [self foo];
};

A commonly prescribed workaround is to simply use a __weak self to avoid the retain cycle:

__typeof(self) __weak weakSelf = self;
self.block = ^{
  [weakSelf foo];
};

However, this can cause problems if self is dealloced in the middle of executing foo. A better strategy is to capture a __strong reference to the __weak self locally within the block. However, I don't know whether the __weak modifier is captured __typeof, and if it is, can I override it with another __strong?

So, one of these, is correct, but which?

A

__typeof(self) __weak weakSelf = self;
self.block = ^{
  __typeof(self) strongWeakSelf = weakSelf;
  [strongWeakSelf foo];
};

B

__typeof(self) __weak weakSelf = self;
self.block = ^{
  __typeof(self) __strong strongWeakSelf = weakSelf;
  [strongWeakSelf foo];
};

C

__typeof(self) __weak weakSelf = self;
self.block = ^{
  __typeof(weakSelf) strongWeakSelf = weakSelf;
  [strongWeakSelf foo];
};

D

__typeof(self) __weak weakSelf = self;
self.block = ^{
  __typeof(weakSelf) __strong strongWeakSelf = weakSelf;
  [strongWeakSelf foo];
};

I hope that C is correct because it doesn't place self inside the block at all, and doesn't require an additional __strong.

EDIT

I totally screwed up my initial question and had my examples wrong. Inside my blocks, all my answers used to be [weakSelf foo] instead of [strongWeakSelf foo].

like image 814
Heath Borders Avatar asked Jan 17 '26 05:01

Heath Borders


1 Answers

C is (almost) what you want:

__typeof(self) __weak weakSelf = self;
self.block = ^{
  __typeof(weakSelf) strongWeakSelf = weakSelf;
  [strongWeakSelf foo]; //use strongWeakSelf, not weakSelf.
};

The __strong or __weak ownership qualifier is different from the type that you get from __typeof__().

B is the same as A, and C is the same as D because local variables are implicitly __strong.

But pedantically all these examples might not do what you want! Since strongWeakSelf isn't actually used the optimizer may be able to remove it.

Also, if you're testing any of these, be aware that the objc_loadWeak runtime function currently used to read weakSelf is (currently) doing a retain+autorelease of the value it loads today. So in practice, each of those examples is equally theadsafe. This isn't guaranteed to always be the case in the future, however.

like image 131
Vincent Gable Avatar answered Jan 19 '26 20:01

Vincent Gable



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!