touchBegan/touchEnd in custom UIWebView
Categories: iPhone on Oct.31, 2009
The main disadvantage in the object UIWebView is lack of methods touchBegan and touchEnd. But this question has been settled by some manipulations with privates possibilities:) Thank you Satoshi Nakagawa :)
PSWebView.h – empty
1 2 3 4 | #import <UIKit/UIKit.h> @interface PSWebView : UIWebView @end |
If you need add method touchBegan then make step by step
1. add after 6 line
1 | - (void)webView:(UIWebView*)sender tappedBeganWithTouch:(UITouch*)touch event:(UIEvent*)event; |
2. after 11
1 | - (void)fireBeganTappedWithTouch:(UITouch*)touch event:(UIEvent*)event; |
3. add after 31
1 2 3 4 5 6 7 8 9 10 11 | - (void)__touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { [self __touchesBegan:touches withEvent:event]; id webView = [[self superview] superview]; if (touches.count == 1) { if ([webView respondsToSelector:@selector(fireBeganTappedWithTouch:event:)]) { [webView fireBeganTappedWithTouch:[touches anyObject] event:event]; } } } |
4. after 46
1 2 3 | Method targetMethod2 = class_getInstanceMethod(klass, @selector(touchesBegan:withEvent:)); Method newMethod2 = class_getInstanceMethod(klass, @selector(__touchesBegan:withEvent:)); method_exchangeImplementations(targetMethod2, newMethod2); |
5. and last addition in source before last “@end”
1 2 3 4 5 6 | - (void)fireBeganTappedWithTouch:(UITouch*)touch event:(UIEvent*)event { if ([self.delegate respondsToSelector:@selector(webView:tappedBeganWithTouch:event:)]) { [(NSObject*)self.delegate webView:self tappedBeganWithTouch:touch event:event]; } } |
For touchMoves similar steps. It’s easy!
PSWebView.m – all implementation in this file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | #import <objc/runtime.h> #import "PSWebView.h" @interface NSObject (UIWebViewTappingDelegate) - (void)webView:(UIWebView*)sender zoomingEndedWithTouches:(NSSet*)touches event:(UIEvent*)event; - (void)webView:(UIWebView*)sender tappedWithTouch:(UITouch*)touch event:(UIEvent*)event; @end @interface PSWebView (Private) - (void)fireZoomingEndedWithTouches:(NSSet*)touches event:(UIEvent*)event; - (void)fireTappedWithTouch:(UITouch*)touch event:(UIEvent*)event; @end @implementation UIView (__TapHook) - (void)__touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { [self __touchesEnded:touches withEvent:event]; id webView = [[self superview] superview]; if (touches.count > 1) { if ([webView respondsToSelector:@selector(fireZoomingEndedWithTouches:event:)]) { [webView fireZoomingEndedWithTouches:touches event:event]; } } else { if ([webView respondsToSelector:@selector(fireTappedWithTouch:event:)]) { [webView fireTappedWithTouch:[touches anyObject] event:event]; } } } @end static BOOL hookInstalled = NO; static void installHook() { if (hookInstalled) return; hookInstalled = YES; Class klass = objc_getClass("UIWebDocumentView"); Method targetMethod = class_getInstanceMethod(klass, @selector(touchesEnded:withEvent:)); Method newMethod = class_getInstanceMethod(klass, @selector(__touchesEnded:withEvent:)); method_exchangeImplementations(targetMethod, newMethod); } @implementation PSWebView - (id)initWithCoder:(NSCoder*)coder { if (self = [super initWithCoder:coder]) { installHook(); } return self; } - (id)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { installHook(); } return self; } - (void)fireZoomingEndedWithTouches:(NSSet*)touches event:(UIEvent*)event { if ([self.delegate respondsToSelector:@selector(webView:zoomingEndedWithTouches:event:)]) { [(NSObject*)self.delegate webView:self zoomingEndedWithTouches:touches event:event]; } } - (void)fireTappedWithTouch:(UITouch*)touch event:(UIEvent*)event { if ([self.delegate respondsToSelector:@selector(webView:tappedWithTouch:event:)]) { [(NSObject*)self.delegate webView:self tappedWithTouch:touch event:event]; } } @end |
Similar posts:

February 3rd, 2010 on 1:44 pm
Thank you, works like a charm with SDK3.1, but it doesn’t work with SDK3.2 (beta):
*** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘*** -[readViewController __touchesBegan:withEvent:]: unrecognized selector sent to instance 0x5041ae0′
Any suggestions?
February 13th, 2010 on 10:04 am
How to make sure that when a user performs a scroll event does not trigger the touch?
March 26th, 2010 on 4:17 pm
Hi,
I have gone through PSWebView. Quite good.
I noticed that script crashing with 3.2
March 31st, 2010 on 10:42 am
the script doesn\’t work with 3.2(beta) ,does blogger have a solution?
June 2nd, 2010 on 2:59 pm
Hi Friend,
It helped me . Thanks for the post. Are you using any private API here or anything that is forbidden by Apple.
June 14th, 2010 on 6:38 pm
anyone sorted this out for 3.2?
June 17th, 2010 on 7:58 pm
For 3.2:
change:
@implementation UIView (__TapHook)
for:
@implementation UIWebView (__TapHook)
June 21st, 2010 on 4:20 pm
not running in ipad Simulator…
#if TARGET_IPHONE
@implementation UIView (__TapHook)
#else
@implementation UIWebView (__TapHook)
#endif
ideas?
June 22nd, 2010 on 11:28 am
Have someone got a solution? Not working with SDK 4.0 too…
July 9th, 2010 on 8:17 am
Have someone got a solution? Not working with SDK 4.0,
but the above mentioned solution i.e. #if TARGET_IPHONE
@implementation UIView (__TapHook)
#else
@implementation UIWebView (__TapHook)
#endif will not solve the single tapevent problem.
Any help would be greatly appreciated,
Thanks in advance,
ASHVIKKY