-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#" touches ");
}
The above method is not calling in my apps. My application description is as under.
I have a MainViewController which loads a ContentViewController in it. ContentViewController has a webview which loads a pdf file.
How to listen the tap of MainViewController's View.
Regards.
I may be not 100% accurate here, but if you place -touchesBegan:withEvent: in your view controller (or its main view) then you will get only those touches that have not been handled by some subviews in the view hierarchy. To intercept all touches you should use UIView subclass for your controller view and override hitTest:withEvent: method in it:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
touchedView = [super hitTest:point withEvent:event];
NSSet* touches = [event allTouches];
// handle touches if you need
return touchedView;
}
For more information see Event delivery section in "Event handling guide" for iOS
Related
I have an OpenGL View with sprites in it which have UIViews with the same position and size on top of the OpenGL view, to make them accessible. The OpenGL View should be able to receive touch events and the UIView on top too. In my UIView class I override the hitTest:withEvent method so the UIViews get the touch input, otherwise only the OpenGL gets the touch:
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
NSEnumerator *reverseE = [self.subviews reverseObjectEnumerator];
UIView *iSubView;
while ((iSubView = [reverseE nextObject]))
{
UIView *viewWasHit = [iSubView hitTest:[self convertPoint:point toView:iSubView] withEvent:event];
if (viewWasHit)
{
return viewWasHit;
}
}
return [super hitTest:point withEvent:event];
}
Now my UIViews receive touch-input but the OpenGL elements underneath don't. How can I change that so both of them receive the touch.
In my opinion in such cases it is best if only your main view receives touches in which you then check if any of the subviews was touched using CGRectContainsPoint for instance. If you really want to override the subviews then I suggest you override the touch methods to call the superview touch methods, for instance to override touchesBegin:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.superview touchesBegan:touches withEvent:event];
//do additional stuff
}
This will work with touches but probably not with gestures since they cancel touch events and have a different pipeline.
I have two view controllers appearing on the screen at the same time using view controller containment, implemented the same as in Apple's code example. Call them view controller A (vcA) and view controller B (vcB), and the container view controller (containerVC).
Each vcA and vcB both have a grid of objects, and I want to be able to drag objects from vcA to vcB. More specifically, I want the touch that originates in vcA to hit the touchesMoved:withEvent method in vcB once it is within the bounds vcB.
I have overridden the touchesMoved:withEvent method on the containerVC, track the touch via a hit test, and tried forwarding the touch down the UIView hierarchy like so:
// in the containerVC
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint locationPoint = [[touches anyObject] locationInView:self.view];
UIView* touchIsInViewControllerA = [vcA hitTest:locationPoint withEvent:event];
if (touchIsInViewControllerA) {
NSLog(#"Touch is in vcA");
return;
}
UIView* touchIsInViewControllerB = [vcB hitTest:locationPoint withEvent:event];
if (touchIsInViewControllerB) {
NSLog(#"Touch is in vcB");
[vcB touchesMoved:touches withEvent:event]; // this causes a crash
}
}
This seems to be recursive, with containerVC pushing the touch event down the hierarchy, then vcB passing the touch event back up the hierarchy.
My question: Is there a way to keep vcB from passing the touch event back up the responder chain to containerVC? Or should I approach this a different way - make vcB a delegate of vcA and leave containerVC out of the equation?
Note: I'm guessing a common response will be to give up the VC containment pattern and keep it all in one view controller, but for reasons not shown in this example I think keeping them separate will work better for me - unless it's utter insanity and super hacky to do so...
This problem can be solved easily by setting individual gesture object for each view controller.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if (touchIsInViewControllerA) {
// calls a delegate of view controller A
}
else
{
// calls a delegate of view controller B
}
}
For example
I have a custom UIView Class, on the view I put a UIButton.
In the View Class
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
NSLog(#"touch view");
}
But when I touch the button, it intercepted view touch message. Is there a way to recieve touches when user touch view's subview?
I noticed when using UIGestureRecognizer bind to the superview, the event can recieved when user touched subview.
There is no (Apple-allowed or stable) way to "pass" touches to another view. Instead, call a method in your other view from your touches method.
I have a transparent UIView on top of a UIScrollView. The UIView determines whether the scrollview is allowed to scroll or not by checking three touchesMoved events. After the events, I want the view to disable user interaction so scrolling will happen. The user shouldn't even notice the delay.
However, having set the view's userInteractionEnabled to NO, it keeps claiming all touchesMoved events until it is released. This means that the user is forced to let go of the view before being able to scroll.
Using hitTest won't work until the view has been released as well. hitTest does not get called while moving.
I would send the touch events to the UIScrollView, but it happily ignores those due to it having its own hidden touch handling.
Any way to make the UIView stop claiming touch events without having to let go of it?
Make the UIView hidden. According to the docs:
A hidden view disappears visually from its window and does not receive input events
See the class reference for more: http://developer.apple.com/library/ios/#documentation/uikit/reference/uiview_class/uiview/uiview.html
try cancelling the touches:
How to cancel a sequence of UITouch events?
p.s. if necessary I assume you are propagating the touches to next responder:
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
[[self nextResponder] touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent *)event {
[super touchesMoved:touches withEvent:event];
[[self nextResponder] touchesMoved:touches withEvent:event];
}
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
[[self nextResponder] touchesEnded:touches withEvent:event];
}
Say I have a UITableview.
If user click on a table cell the cell is selected.
The same way I have MKMapView. If a user select an annotation than the annotation is selected.
Now I want to arrange that something happened when I click an empty part of the cell.
So I add a tap gesture.
But then when I click, the non empty part of the cell, like the table, and stuff, the cell and mapview don't get selected again.
Only the gesture selector get called.
After the gesture selector is called I want to "pass" the tab back to table cell and mkmapview. How would I do so?
Call your code in the touchesEnded method of your subclass and then call touchesEnded on the superclass, or called it on a specific view object:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[self someMethod];
[super touchesEnded:touches withEvent:event];
}
OR
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[self someMethod];
[mapView touchesEnded:touches withEvent:event];
}