18

I was thinking, if you assign the target as self in the gesture recogniser's initWithTarget:action: method, will you cause a circular retain? Since self will retain the recogniser in self.gestureRecognizers and it's possible the gesture recogniser to also retain self in initWithTarget:action.

Would the following be a solution for it?

__weak VRDrawer* weakSelf = self;
UIGestureRecognizer* tapRec = [[UITapGestureRecognizer alloc] initWithTarget:weakSelf
                                                                      action:@selector(handleTap:)];
vikingosegundo
  • 52,040
  • 14
  • 137
  • 178
Meda
  • 2,776
  • 4
  • 20
  • 31
  • 3
    What makes you think the gesture recognizer will retain the target? It should be pretty simple to print `[self retainCount]` before and after the code that allocates the gesture recognizer to see if it changes. – Geoff Hackworth Jan 30 '13 at 20:24
  • 5
    @GeoffHackworth: http://www.whentouseretaincount.com – vikingosegundo Jan 30 '13 at 20:26
  • 1
    @GeoffHackworth I don't know if it does retain the target of course, but since the docs mention nothing about it, one should wonder. – Meda Jan 30 '13 at 20:32
  • When one wonders, one tests. Use retainCount and see what happens! You get your answer and you remove the call to retainCount. It couldn't be more simple. – Geoff Hackworth Jan 30 '13 at 20:54
  • 2
    @GeoffHackworth you realise that the output from `retainCount` is not reliable right? You also know that you can't use it under ARC right? And `__weak` means I'm using ARC, in case you wonder... – Meda Jan 30 '13 at 21:45
  • 2
    @GeoffHackworth, belive me: the website is right — never use `retainCount` even not for printline-debugging. – vikingosegundo Jan 30 '13 at 23:33

2 Answers2

22

I completely understand confirming something with the lack of documentation can feel unsettling. The important thing to note is that, by over a decade of convention, target-action relationships are never strong. Here's the relevant docs. Note the part that says:

Control objects do not (and should not) retain their targets.

"Retain…" in the MRC way of saying "Holds a strong reference to…"

Given this is the documented convention for this type of interaction, it's safe to assume that, if UIGestureRecognizer's target-action implementation did retain objects, that anomaly would be strange enough that it would show up in its docs.


P.S. You don't have to worry about the note that refers to controls retaining targets in memory-managed environments. "Memory-managed" refers to the (now depricated) garbage collection in Cocoa. Neither MRC or ARC is memory-managed.

jemmons
  • 18,605
  • 8
  • 55
  • 84
  • Meanwhile, in other, not-too-distant worlds, for NSNoticationCenter it's the opposite: "You must invoke removeObserver: or removeObserver:name:object: before any object specified by addObserverForName:object:queue:usingBlock: is deallocated." Which kind of explains why my removes in the `dealloc` method never work. – Dan Rosenstark Apr 12 '16 at 19:03
4
UIGestureRecognizer* tapRec = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];

This does not retain self. It would also be noted in the docs

You need to add a recognizer to a view. That view will retain the recognizer. no retain cycle.

[aView addGestureRecognizer:tapRec];

addGestureRecognizer: docs do mention, that the view retains the recognizer


as you are using ARC, this is all you have to do

UIGestureRecognizer* tapRec = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
[aView addGestureRecognizer:tapRec];
vikingosegundo
  • 52,040
  • 14
  • 137
  • 178