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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With