1

Given that self is unsafe unretained in Objective-C, can we generally say that there is no good reason to ever call methods or access properties on weak objects? ie. never do this:

__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
    [weakSelf doStuff];
});

Sure, technically this may be ok if there is another strong reference to self that is guaranteed to remain in scope until after doStuff is called, but this is a very poor reason.

If there are no good reasons, then wouldn't it be a good idea for the compiler to simply reject such calls, at least behind a compiler option?

danh
  • 62,181
  • 10
  • 95
  • 136
John K
  • 859
  • 1
  • 8
  • 16
  • In answer to your question, there are lots of excellent reasons to use the general `weakSelf` pattern, though, for practical reasons, there's little purpose in doing it precisely like you have in your example. That having been said, we most certainly would not want the compiler to reject this pattern. We can easily construct scenarios where we'd want to do precisely this. E.g., what if this was in a network request completion handler from a view controller and it finished updating the model object and `doStuff` was then updating the UI? You might do something very much like what you have here. – Rob Feb 21 '17 at 18:05
  • That was a typo, I meant unsafe unretained. You certainly don't need to call [weakSelf doStuff] for the network request. You can always do typeof(self) strongSelf = weakSelf; [strongSelf doStuff]; Apparently, for weak objects, the object essentially becomes strong during doStuff so adding a strongSelf would be redundant in this case. – John K Feb 21 '17 at 18:22
  • Changed adjectives describing reasons from "strong" and "weak" to "good" and "poor", so as to not overlap confusingly with the clang memory management terminology. Also, consider that a *truly __weak* reference would be pointless, because it would be released immediately after assignment. – danh Feb 21 '17 at 18:46
  • Good call changing the adjectives. – John K Feb 21 '17 at 19:11

2 Answers2

2

From the document you referenced:

For __weak objects, the current pointee is retained and then released at the end of the current full-expression. This must execute atomically with respect to assignments and to the final release of the pointee.

In other words, weakSelf is automatically retained for the duration of the doStuff method, so it's safe.

Generally, you would convert a weak reference into a strong reference if you're calling more than one method/property.

Darren
  • 25,520
  • 5
  • 61
  • 71
  • Ah ok. My question was coming from the answers in this question: http://stackoverflow.com/questions/32468758/objective-c-arc-does-a-method-retain-self. I think those answers are wrong then. – John K Feb 21 '17 at 18:19
-1

can we generally say that there is no strong reason to ever call methods or access properties on weak objects

No, that makes no sense. You are calling methods on weak objects all the time! For example, in Cocoa, most delegate objects are weak — as they would need to be, since it would be wrong for an object to retain its delegate. Yet calling methods on a delegate is the essence of the delegate pattern; otherwise, what is a delegate for?

Example: here's how the UIApplication delegate is declared:

@property(nullable, nonatomic, assign) id<UIApplicationDelegate> delegate;

That is a non-ARC weak reference (that is what assign means). Yet you would never say no messages can be sent to the app delegate, would you?

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Never calling methods on weak objects doesn't imply that you would never use them. It just implies that you would have to make them strong first. But as Darren pointed out, the compiler already does this for you. – John K Feb 21 '17 at 18:29
  • But I don't believe that. The compiler doesn't make the weak `delegate` strong. On the contrary, sending a message to a `delegate` that no longer exists is a classic "dangling pointer" crash situation. It is _unsafe_. Nothing makes it strong; if it did, we wouldn't be crashing. But this is not a silly or bad situation; you just have to take steps to keep it safe. Making sure the delegate outlives the object with a weak reference to it is part of your job, that's all. But to say it's somehow not a weak reference is just nonsense. Of course it's weak. – matt Feb 21 '17 at 18:32
  • What don't you believe about the part of the documentation that says "For __weak objects, the current pointee is retained and then released at the end of the current full-expression. ". If it's retained, then it will not be released (just as if there was a strong variable referencing it). If the delegate is deallocated, the weak reference will become nil. Using a nil object will not crash unless you do something specific with it like add it to an array or access an ivar directly. That's a completely separate discussion and not the question here. – John K Feb 21 '17 at 18:37
  • The "question here" was "can we generally say that there is no strong reason to ever call methods or access properties on weak objects". And my answer, which is correct whatever you may think, is: No, we cannot generally say that at all. Keep in mind that you are the questioner; you might not know the truth when you hear it. You might even downvote it. But it would remain the truth. – matt Feb 21 '17 at 18:43
  • Your yes/no answer is correct but the extended answer is not. In your answer you implied that weak objects could not be used at all if we could not call methods and access properties on them. This is not correct because you could simply strongify the objects first. But of course as Darren mentioned this is already done for you. And as you mentioned, you don't believe Darren. So, keep in mind that you might not know the truth when you hear it (or read it directly in ARC documentation). – John K Feb 21 '17 at 19:09