ignore touch over a barButton - ios

I made a custom split view controller, and I have tried to mimic the standard one as much as possible.
One feature I have is if the device is in portrait and the master view is displayed, if you tap on the details view, the master view will hide.
I use this code in the details view to accomplish this.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
return [super hitTest:point withEvent:event];
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
// Detect touches on the details View and notify the Split View controller
if(point.y != self.touchLocation.y)
{
if (_delegate && [_delegate respondsToSelector:#selector(detailsViewDidTapDetails:)])
[_delegate detailsViewDidTapDetails:self];
}
return [super pointInside:point withEvent:event];
}
The problem I am having, is if the detailsView is filled with a view that has its own navigation bar, then any buttons pressed in the navigation bar trigger the 'details view tapped' methods displayed above. This conflicts with adding the 'Show Details' button that you place inside a nav bar. Essentially what happens, is the methods to hide/show the master View is called twice back to back.
I need a way to ignore any taps on top of my 'hide/show details' button. I have a reference to the button, I just need to ignore taps on it within my hitTest / pointsInside methods.

Related

Automatically passing events from ChildViewController to parentViewController

I can't figure out how enable iOS to pass events from a childViewController down to its parentviewcontroller.
My childviewcontroller is like an overlay it's root view is transparent and it's opaque views cover a dynamic area - potentially the the entire parentviewcontroller (thus the root view of the childviewcontroller has the same frame as the parent).
Though only the opaque part of the childViewController's views should receive events. All other events I would like to get forwarded in the responderChain down to the parentviewcontrollers views. Just as if all views were sharing one viewcontroller.
I have made an instance of this class:
#interface SilentView : UIView
#end
#implementation SilentView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *hitView = [super hitTest:point withEvent:event];
if (hitView == self) {
return nil;
}
return hitView;
}
#end
the rootview of my childViewController. That works for me.

Pass an event on the whole view hierarchy

I have created a "classic" category on ui controller to present in my way an other controller.
#interface UIViewController (QZPopup)
- (void)presentPopupViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion;
- (void)dismissPopupViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion;
#end
The category adds:
a blurred view on top of the calling controller view
an invisible view on top of all the screen. this invisible view must catch touch event to dismiss the popup and after having dismissed the popup, I also want to transmit this event to do anything required.
For my usage, I have a UIController embedded in a UINavigationBarController. I want to have the part below the navigation bar blurred and the navigation bar visible. A touch on the blurred view just dismiss and a touch on the navigation bar must dismiss AND do anything required by touched items in the navigationbar.
Visual is ok on my side, but I have trouble to pass the event and reach the navigationbar. For the moment I have subclassed UIView in QZPopupDismiss like below:
#implementation QZPopupDismiss {
touchCallback _touchCompletion;
}
- (instancetype)initWithFrame:(CGRect)frame andTouchCompletion:(touchCallback)completion {
if (self = [self initWithFrame:frame]) {
_touchCompletion = completion;
self.userInteractionEnabled = YES;
}
return self;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
// first do the touch completion
_touchCompletion();
// pass the event to the view hierarchy
[super touchesEnded:touches withEvent:event];
}
#end
But the fact is that, in touchsEnded, super does not reach the navigation bar. How can I pass my event to the whole view hierarchy to reach the navigation bar items ?

keyboard is not dismissing if i use modal segue

I am using simple Modal segues between view controllers and i it is not dismissing the keyboard. I tries [textField resignFirstResponder] on view will disappear method but still no luck.
I am not using any Navigation Controllers, just simple View Controllers.
I also tried doing this but still no luck. Need Help.
View Controller A ---------> View Controller B
in View controller B. I called [self disablesAutomaticKeyboardDismissal] in viewDidLoad.
and I've overridden in it like so
-(BOOl)disablesAutomaticKeyboardDismissal
{
return NO;
}
This one could help you too
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self.view endEditing:YES];
}
With this, when you tap outside the textfield , the keyboard disappear

Control-drag to create IBAction in Xcode 5 to dismiss keyboard?

I have a view controller with a text field. I'm trying to create an IBAction to dismiss they keyboard when user taps outside the text field by control-dragging from outside the text field in the Xib file to my .h file, but I don't get the option to choose "Action," only "Outlet" and "Outlet collection." I don't even get a window that asks me to choose when I control drag inside a *.m file. What am I missing?
I was able to do this in Xcode 4.
When you ctrl-drag from "outside the text field", you are most likely interacting with the top-level view of the view controller. This is a UIView object which does not have actions. Only views that inherit from UIControl have actions, e.g. buttons, text fields. This is not an XCode 4 vs 5 issue -- it's always been this way.
In your view controller, override touchesBegan:withEvent:. Make a call to [self.view endEditing] to dismiss the keyboard.
This is possible because your view controller inherits from the UIResponder class, as do UIViews. When the user touches something on the screen, the event gets passed up the responder chain, e.g. from subview to parent view to parent view controller etc., until one of those responders decides to respond to or purposefully discard that event. By overriding touchesBegan:withEvent:, your view controller can handle that event and do something meaningful (like dismiss the keyboard).
A simple solution would be using a simple UITapGestureRecognizer added to the "main" view.
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(hideKeyboard)];
gestureRecognizer.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:gestureRecognizer];
Then the method hideKeyboard:
- (void)hideKeyboard
{
[[UIApplication sharedApplication] sendAction:#selector(resignFirstResponder) to:nil from:nil forEvent:nil];
} <br>
The tap is sent through views until it finds one that could manage it, like the view controller view that triggers the gesture.
Use this code on your .m file
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
selectedTextField = textField;
return YES;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[selectedTextField resignFirstResponder];
}

How to stop gesture swiping back to previous view controller?

In one of my view controllers I have a carousel that the user can swiper through.
But if the user swipes up in the top left hand corner of the screen they can drag back the previous view controller.
How can I stop this? It could be something to do with this?
- (void) viewWillDisappear:(BOOL)animated
{
[self.carousel setHidden:YES];
}
- (void) viewWillAppear:(BOOL)animated
{
[self.carousel setHidden:NO];
}
https://developer.apple.com/library/ios/documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html#//apple_ref/occ/instp/UINavigationController/interactivePopGestureRecognizer
Set the interactivePopGestureRecognizer's enabled property to NO on your UINavigationController

Resources