How to Pass on User Events to Another View after processing it - objective-c

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];
}

Related

How to make touches propagation?

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.

UIView smaller than another UIView

I have an UIView high 30, than i add an UITableView as subview with 30 as origin.y. Because the table remains “under” the main view I cannot select the cells. Consequently I have implemented this method:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"Tocco intercettato");
if (oldSet && oldEvent) {
[table touchesEnded:oldSet withEvent:oldEvent];
}
oldSet = touches;
oldEvent = event;
[table touchesBegan:touches withEvent:event];
[table touchesEnded:touches withEvent:event];
}
The taps work, but the slides does not work and consequently I cannot slide the table. Some idea in order to resolve?
Passing the touches from an overlying UIView to an underlying UITableView does not work (as you're seeing, the taps go through but not the scrolling movements). This is because UITableView (as a subclass of UIScrollView) does all sorts of under-the-hood weirdness with the responder chain (your code is also kind of odd, where you call both touchesBegan and touchesEnded from the overlying view's touchesBegan method, but this isn't why you can't scroll the table).
A simple way to achieve what you want (assuming I've understood that correctly) is to override the hitTest:withEvent: method on your overlying view and have the method return the underlying UITableView (instead of self, which is the default implementation):
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UITableView *tv = (UITableView *)[self.superview.subviews objectAtIndex:0];
return tv;
}
Note that this code assumes the UITableView is the first view added to your view controller, and that the overlying UIView is added after that.
Edit: OK, after re-reading your question, I think I understand your question. You have a main view with a height of 30, and to that view you've added a UITableView at y = 30. I think adding this method to your main view will do what you need:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if (point.y < self.frame.size.height) {
return self;
} else {
return myTableView; // assumes myTableView is a reference to the
// UITableView that you've added
}
}
Essentially, you're telling the OS to pass all touches on to myTableView if they're outside the bounds of your main view.
However, a simpler way would be to add both the 30-pixel-high main view (the orange thing) and the UITableView as subviews of another view (or view controller). That way, you wouldn't have to do anything kludgy to get your table to behave like a normal table.

How to make a UIView ignore touches without releasing it?

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];
}

resign keyboard when losing focus on uisearchbar

I'm making an UISearchBar option in the navigationbar of my app.
My app consists of multiple views and subviews.
I have this mainview which has 3 other views on himself. one of it is empty (for now) the other 2 have tableviews on them.
I want my keyboard to show when I'm searching and hide when i'm doing the actual search or when i touch/click outside the uisearchbar.
Im using the searchbardelegate as is required.
Im able to hide the keyboard using [searchBar resignFirstResponder] in the following ways.
When im pressing the return key.
When i cancel search manually
When i press any of the keyboard buttons to search or cancel.
When i touch an empty part of the screen using
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
if ([mySearchBar isFirstResponder] && [touch view] != mySearchBar) {
[mySearchBar resignFirstResponder];
}
[super touchesBegan:touches withEvent:event];
}
What i not seem to be able to do is make it respond to touching one of my 2 tableviews. Or when im refilling the mainview to contain something different entirely.
Ive tried changing the touchesbegan method to resign the searchbar when touching the tableviews but it hasnt worked so far.
I've tried several other things found by my dear friend mr. google, but it all seems to be something other then I need.
Anyone have any ideas of what I might do to fix this problem?
EDIT:
It appears so that, when using breakpoints, touchesbegan-method does respond to the backgroundview but it doesnt respond when i touch either of the tableviews or the navigationbar (containing the uisearchbar).
Solved it!
- (BOOL) searchBarShouldBeginEditing:(UISearchBar *)searchBar
{
[self.myViewController1.customView1 setUserInteractionEnabled:NO];
[self.myViewController2.customView2 setUserInteractionEnabled:NO];
[searchBar setShowsCancelButton:YES animated:[mySettings animation]];
return YES;
}
I started by shutting down the userInteraction on my 2 subviews, at the moment I start using the searchBar.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
if ([self.mySearchBar isFirstResponder] && [touch view] != self.mySearchBar)
{
[self.mySearchBar resignFirstResponder];
[self.myViewController1.customView1 setUserInteractionEnabled:YES];
[self.myViewController2.customView2 setUserInteractionEnabled:YES];
}
[super touchesBegan:touches withEvent:event];
}
Then when I click/tap/touch outside the searchBar I first resign the keyboard which is first responder still AND AFTER that I set userInteraction back on for the 2 subviews.
The order of doing this is vital!
This piece of code allows u to resign the keyboard in a single mainViewController even when it is crowded with a massload of subviews.
Have you tried this,
UISearchBar *searchBar;
Next set the Getter and Setter Property of UISearchBar.
and call the any method
[searchBar resignFirstResponder];

touchesBegan not responding

-(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