Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect the drag end event of an UITableView?

I need to get notified when an UITableView's drag has come to an end.

But I'm working on an UITableView's category, so I can't use scrollViewDidEndDragging:willDecelerate: to archive this.

I tried use KVO to observe on dragging Key Path:

[self addObserver:self forKeyPath:@"dragging" options:NSKeyValueObservingOptionNew context:nil];

But observeValueForKeyPath:ofObject:change:context: didn't get called, since UITableView.dragging doesn't have and setter and this property is not compliant with KVO.

Is there any other method to archive this expect for using scrollViewDidEndDragging:willDecelerate:?

Any help is grateful! Thanks!

like image 949
OpenThread Avatar asked Feb 11 '13 17:02

OpenThread


2 Answers

Edit: My solution below was the first thing to come in mind and turned out to be rather hacky and may be unsafe to use in case Apple decides to change the internals of the UIScrollView class. See the answer suggested by Mazyod which should be safer and more straightforward.


This is implementation-dependent and may be changed by Apple in future iOS updates, but currently UIScrollView class seems to rely on gesture recognizers for managing user interaction and UITableView being a subclass of the scroll view class does the same.

If you go to UIScrollView.h of the UIKit framework, you can notice a suspicious _pan ivar which has an id type, but seems to actually be a UIPanGestureRecognizer.

So I've tried this, and it seems to work.

 [_tableView addObserver: self 
              forKeyPath: @"pan.state" 
                 options: NSKeyValueObservingOptionNew 
                 context: nil];

When dragging the table view, state of the gesture recognizer changes several times, and when you stop dragging, state receives its last change to the value of UIGestureRecognizerStateEnded.

Please note that although this seems to do the trick, some other problem may stand in your way. It is generally not a good idea to override existing class methods in a category since the original implementation becomes inaccessible after that. Documentation on the NSKeyValueObserving informal protocol states that

NSObject provides an implementation of the NSKeyValueObserving protocol that provides an automatic observing capability for all objects.

So if you override observeValueForKeyPath:ofObject:change:context: in a category, the default implementation will be inaccessible (and we cannot be sure that UITableView or UIScrollView do not user KVO for something). That may cause some unexpected errors.

like image 116
Egor Chiglintsev Avatar answered Nov 15 '22 14:11

Egor Chiglintsev


Egor Chiglintsev's answer reminded me I can observe the panGestureRecognizer property already exposed in UIScrollView. It should be much safer than pan. But then.. I found out I can just add myself as a target!

[_scrollView.panGestureRecognizer addTarget:self action:@selector(gestureRecognizerUpdate:)];

This works great for me!

like image 36
Mazyod Avatar answered Nov 15 '22 13:11

Mazyod