2

When I pass self as an argument to a function, does it make any difference if I weakify it first?

For example:

__weak __typeof(self) weakSelf = self;
[self.someObject doWorkWithDelegate: weakSelf];

In the body of the doWork function it assigns it to a strong property

@property (strong) Foo* fooDelegate;

(I know this is terrible, don't get sidetracked).

This will still be a strong reference and cause a memory cycle despite theh fact that I "weakified" the reference first, correct?

Bonus Question: How can I check this myself?

Makaronodentro
  • 907
  • 1
  • 7
  • 21

2 Answers2

3

It is the variable weakSelf which is weak. That is, ARC does not emit a retain when a value is assigned to it, nor a release when it goes out of scope (or is assigned a different value).

Since the fooDelegate property is strong, assigning to it releases any old value it may have had and retains the newly-assigned value.

So, yes, that will be a strong reference. It's not clear from what you posted whether it will constitute a retain cycle. The name of the method suggests that the delegate will be cleared (thus released) after the work has been completed. In that case, it's not a problem. It would only be a problem if self.someObject maintained the strong reference until it itself was released and self maintained a strong reference to someObject until self was released.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • Thanks that part of ARC logic was exactly what I was missing. Is there a convenient way to identify whether a reference is weak / strong whilst debugging? Or not really since all __weak does is increment the ARC reference count – Makaronodentro Mar 20 '18 at 15:50
  • Ignore the comment this answer gives a thorough explanation https://stackoverflow.com/questions/8863269/how-do-i-verify-reference-count-in-arc-mode – Makaronodentro Mar 20 '18 at 15:51
0

An important aspect of the original question could be further clarified. "When I pass self as an argument to a function, does it make any difference if I weakify it first?"

Note that in the example code block:

__weak __typeof(self) weakSelf = self;
[self.someObject doWorkWithDelegate: weakSelf];

ARC will perform a retain on each of the objects passed, including the receiver (i.e. self.someObject and weakSelf), and then a release on each when complete, allowing weak objects to be safely used for the lifetime of the called method. So the answer would be no, it doesn't make a difference to make it weak first because it will be strong for the duration of the call.

If the weak variable was simply referenced within a code block callback from the method, then it will still be weak within that scope.

So this is a common pattern to use a weakSelf variable within a block callback to call another method, foo, which then can safely use self because it is no longer weak during that execution of foo. But if self goes away before the callback is executed, then [weakSelf foo] will simply never be called because weakSelf has gone nil.

__weak __typeof(self) weakSelf = self;
[self.someObject doWorkWithCallback:^{
  [weakSelf foo];
}];

- (void)foo
{
  // Safely use self here.
  [self doMoreWork];
}
terence
  • 51
  • 2