Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct way of attaching/removing of UIGestureRecognizers

What is the correct way of attaching and removing a UIGestureRecognizer on a view?

I usually create and attach UIGestureReconizers in -viewDidLoad. Shall I use removeGestureRecognizer in the -viewDidUnload? Or are they automatically removed?

For example is it a better way to create a UIGestureRecognizer property and initialize it in the viewController's init method and then attach/remove this gestureRecognizer property in -viewDidAppear/-viewDidDisappear?

(Note I'm using ARC)

Thanks.

like image 474
mrd3650 Avatar asked Apr 11 '12 10:04

mrd3650


People also ask

What is UIGestureRecognizer?

UIGestureRecognizer tracks the touch behavior on-screen interpreted by the user such as tap, pinch, rotate, swipe, pan, and long press and acts on the recognition based on the action method written. With the introduction of UIGestureRecognizer, it definitely will save you more time from writing additional code.

What is UITapGestureRecognizer Swift?

UITapGestureRecognizer is a concrete subclass of UIGestureRecognizer . For gesture recognition, the specified number of fingers must tap the view a specified number of times. Although taps are discrete gestures, they're discrete for each state of the gesture recognizer.


1 Answers

Essentially you can create, add, and remove gesture recognizers when it makes sense. And "when it makes sense" varies depending on a few things, but usually just on whether you will keep them as ivars. With ARC the key is managing strong references; With ARC ivars are strong by default.

So let's say you add a tap recognizer. In this scenario you don't need to access the recognizer again. I would create it like this:

-(void)viewDidLoad{
    [super viewDidLoad];
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
    [self.view addGestureRecognizer:tap];
}

With this scenario, you need do nothing else to manage this recognizer. The view system is holding strong reference to it. All you do is sit back and wait for it to call handleTap:. When the view unloads this tap recognizer will be deallocated.

This scenario would also not be a good one to add this recognizer in viewWillAppear: since it's not hard to imagine a series of events that would lead to multiple recognizers being created.

So logically if you want to add a recognizer in the appearance methods you would have to hold some sort of reference to them in an ivar. But again that is not always a bad idea. Generally the reason you would want reference to your recognizers is to help in the logic of <UIGestureRecognizerDelegate> methods, if they are used.

I personally would never add a recognizer in the initWith.. method for attachment later. The only advantage is that any recognizer you create there would be kept around the entire life of the view controller. But since a recognizer is pretty clearly part of the view system this kind of muddies-up the MVC that Cocoa is big on. Also in a low memory condition view of controllers on the navigation stack are purged, but in this case the recognizer might remain using memory(not that there huge objects) for no real reason.

You certainly could add a recognizer in an view(Will/Did)Appear: method and remove it in view(Will/Did)Disappear:. Not my preference. I don't think that just because a modal view is presented and removed or a navigation push/pop has happened that I should remove and re-add my recognizers.

I would recommend nearly always using viewDidLoad to instantiate and attach your recognizers. Just remember to nil-out any strong references to them in viewDidUnload to help in a low memory situation. And again with ARC there is no need to do anything with ivars in dealloc.

like image 160
NJones Avatar answered Sep 28 '22 11:09

NJones