I have a problem with a GLKViewController (subclass) used in a Storyboard: it refuses to handle tap events.
I added a Tap Gesture Recognizer to the GLKViewController (subclass) in the Storyboard and linked it to a 'tapDetected' method:
- (IBAction) tapDetected:(id)sender {
NSLog(#"tap\n");
[self.navigationController setNavigationBarHidden: ![self.navigationController isNavigationBarHidden]];
} // tapDetected
This exactly how I manage - successfully - the taps in other view controllers in the same Storyboard. Only the GLKViewController does not receive the event: neither the log nor the navigation bar are affected by the tap.
I searched for any specific need of GLKViewControllers but could not find any. Do you have any idea and/or suggestion?
It looks like if I add a touchesBegan method everything works ok. So the question is: what's the point of the gesture recognizer in the Storyboard?
Related
I'm attempting a project using the Xcode (version 9.1 9B55) Master-Detail template, using one Storyboard for both iPhone and iPad.
I want to use the built in popover segue, which ideally will show a popover when the size class is appropriate, or a modal view controller when the size class is compact (iPhone in portrait).
What I am finding is that it works just fine for iPad, but when I run it on an iPhone, you can't touch outside the popover to dismiss as I would expect.
When on iPad, popoverPresentationControllerDidDismissPopover is called and all is well.
When on iPhone, the popoverPresentationControllerDidDismissPopover never gets called and you cannot dismiss the popover.
To reproduce, I did this:
Create new Master-Detail App
New - File. Cocoa Touch Class, called MyPopoverViewController
In Storyboard:
Create new view controller, change class to MyPopoverViewController.
On MasterViewController, add bar button item "Popover". Control-drag from this to MyPopoverViewController. Set segue Kind to "Present As Popover". Set Identifier to "thePopover".
In MasterViewController.h, add UIPopoverPresentationControllerDelegate:
#interface MasterViewController : UITableViewController <UIPopoverPresentationControllerDelegate>
In MasterViewController.m:
#import "MyPopoverViewController.h"
In viewDidLoad, comment out two lines which create the "Add Button".
In prepareForSegue:
} else if ([[segue identifier] isEqualToString:#"thePopover"]) {
NSLog(#"MVC prepareForSegue thePopover");
MyPopoverViewController *myPopoverController = segue.destinationViewController;
myPopoverController.popoverPresentationController.delegate = self;
}
Add three UIPopoverPresentationControllerDelegate delegate methods:
- (void) prepareForPopoverPresentation:(UIPopoverPresentationController *)popoverPresentationController {
NSLog(#"MVC prepareForPopoverPresentation");
}
- (void) popoverPresentationControllerDidDismissPopover:(UIPopoverPresentationController *)popoverPresentationController {
NSLog(#"MVC popoverPresentationControllerDidDismissPopover");
}
- (BOOL) popoverPresentationControllerShouldDismissPopover:(UIPopoverPresentationController *)popoverPresentationController {
NSLog(#"MVC popoverPresentationControllerShouldDismissPopover");
return TRUE;
}
I tried this also, but all it does is force popover in portrait mode (which I don't want); doesn't change the lack of popover delegate calls and doesn't allow us to dismiss popover:
-(UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
return UIModalPresentationNone;
}
I'm hoping there is something simple I'm missing here. I have uploaded a sample project here, which is exactly what I've described above:
https://github.com/johnstewart/MasterDetailPopoverTestProject
How do I allow iPhone to also dismiss popovers by touching outside the popover?
If I understand your question correctly your problem appears on iPhone 8 Plus in landscape mode.
In this situation, the presented popover actually is not a popover but a normal presented view. Visually it looks like a sheet that appears from the botton of the screen. In order to close such a view, you have to add your own button to do this.
If you want to show a real popover, you must implement:
adaptivePresentationStyleForPresentationController:traitCollection:
to return UIModalPresentationNone. Note the additional parameter traitcollection:. UIAdaptivePresentationControllerDelegate contains two similar methods. In your project you already implemented the method:
adaptivePresentationStyleForPresentationController:
Change this to the former method and everything should work.
I'm having a weird reaction in 1 of my view when swipe to back.
It did not go back to my previous page but other pages does not have this issue. Also, it perform the previous page viewWillAppear code after the swipe.
I did not set any custom back buttons for the views but it is having different effect.
--Edit--
In my previous page that call the affecting page
ViewControllerA *view = [[ViewControllerA alloc] initWithNibName:#"ViewControllerA" bundle:nil];
[self.navigationController pushViewController:view animated:YES];
In my affecting page I only declare viewDidLoad function.
All my navigation for other classes is using the above calling.
By normal clicking the back action at the navigation bar, it will go back to the previous page normally.
--Edit 2--
My current setup is ViewA > ViewB > ViewC where ViewC is where the bug is happening.
At ViewB when I swipe at the edge, it can go back to ViewA.
At ViewC when I swipe at the edge, viewWillAppear in ViewB called but ViewB is not shown.
Tried putting #kaushal answer
if ([self respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
self.navigationController.interactivePopGestureRecognizer.delegate; //check UIGestureRecognizerDelegate delegate set properly.
}
in both ViewB and ViewC but it did not trigger.
--Edit 3--
I tested my other features flow and it seems that some have this same problem upon entering the third view and some is on the forth view.
In ViewDidAppear: use this code :
if ([self respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
self.navigationController.interactivePopGestureRecognizer.delegate; //check UIGestureRecognizerDelegate delegate set properly.
}
And check UIGestureRecognizerDelegate is not nil.
Simple question that I'm currently having trouble as to how to get started.
I have a ViewController with multiple images/icons, and I would like to have new view controllers for each image/icon that is selected. I have a segue (show) from my initial view controller to my new one...but now how do I code it so when I click on a specific image it'll segue to the corresponding VC I want?
Thanks in advance!
If all of your Images/Links goes to one kind of ViewController, you can link it with segue in your interface builder and so you use just -performSegueWithIdentifier and seed it with your data or model corresponding to your ViewController.
For getting touch events and handling it, you can use delegate method which each subviews call their delegate when touch event catches. Assume below code for better imagination:
//Added in initiation of SubView
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGestureUpdated)];
//This function will be fired when gesture recognized
- (void)tapGestureUpdated {
if ([self.tapDelegate respondsToSelector:#selector(onItemTapped:)]) {
[self.tapDelegate onItemTapped:self.item];
}
}
But if you're showing to different types of ViewControllers, for each kind you should add segue and ViewControllers.
Superview will call next ViewController like this:
[self performSegueWithIdentifier:#"showNextViewControllerSegue" sender:self];
So there is such event chain for handling it:
UITapGestureRecognizer -> Your SubView -> Call it's delegate
(SuperView) -> Call next segue according to subView's type.
SWRevealViewController dismiss keyboard on swipe
Problem is the same but this answers does not help me.
There are some solutions in the given link.For example I don't have any #if macros to delete and I get an error when I write revealController.delegate = self; in AppDelegate.m
And the delegate method below never get called.
- (void)revealController:(SWRevealViewController *)revealController didMoveToPosition:(FrontViewPosition)position
{
//Never get called
}
I searched the Internet and did everything mentioned in the given link.
I am using SWRevealViewController V 1.1.3 https://github.com/John-Lluch/SWRevealViewController/releases
The problem is: I have a UITextField inside a ViewController which behaves as a Front View.When I click on UITextField, keyboard shows up, then I swipe to see my ViewController which behaves as Rear View but keyboard is still there and I can't hide it.
How can I make it possible?
I tried using willMove to position.........However it displays the keyboard when the Rear View controller pops up soon after the keyboard gets hidden..........
For me this worked perfectly....
func revealControllerPanGestureShouldBegin(revealController: SWRevealViewController!) -> Bool {
self.view.endEditing(true)
return true
}
Hi there, Now I'm trying to create a Pop-OverView using an Xcode
storyboard. Firstly, I have
rootViewController, UIViewController, and UITableViewController
I want the UIView to act as a page flip and the UITableView will show popOver under the navigationBar item controller.
For the UITableView, I want to make a Pop-Over under NavigationBar controller. The problem is, when I touch the Navigation item to show the UITableViewController, it shows correctly, but when I try to close the Pop-Over View, it won't close. And then, the navigation item doesn't work well. It shows multiple instances of popOverView when I touch it multiple times.
This doesn't seem to make sense to me. Can anyone help me out or tell me where to find documentation / tutorials on this?
UPDATE:
For the UIPopOverController, it seems to work well now, but it is still bugging me when I touch a Navigation Item multiple times. It will show multiple instances of PopOver. How can I handle it, so it will show only one instance?
I had the same problem and mostly found the solution here. Basically you change the action of the button each time it's pressed to either display or dismiss the popover. Here's the code I ended up with:
#interface FilterTableViewController : UITableViewController {
UIPopoverController *editPopover;
id saveEditSender;
id saveEditTarget;
SEL saveEditAction;
}
-(void)prepareForSegue:(UIStoryboardPopoverSegue *)segue sender:(id)sender{
if([[segue identifier] isEqualToString:#"EditFilterSegue"]){
// Save the edit button's info so we can restore it
saveEditAction = [sender action];
saveEditTarget = [sender target];
saveEditSender = sender;
// Change the edit button's target to us, and its action to dismiss the popover
[sender setAction:#selector(dismissPopover:)];
[sender setTarget:self];
// Save the popover controller and set ourselves as the its delegate so we can
// restore the button action when this popover is dismissed (this happens when the popover
// is dismissed by tapping outside the view, not by tapping the edit button again)
editPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
editPopover.delegate = (id <UIPopoverControllerDelegate>)self;
}
}
-(void)dismissPopover:(id)sender
{
// Restore the buttons actions before we dismiss the popover
[saveEditSender setAction:saveEditAction];
[saveEditSender setTarget:saveEditTarget];
[editPopover dismissPopoverAnimated:YES];
}
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
// A tap occurred outside of the popover.
// Restore the button actions before its dismissed.
[saveEditSender setAction:saveEditAction];
[saveEditSender setTarget:saveEditTarget];
return YES;
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// Before we navigate away from this view (the back button was pressed)
// remove the edit popover (if it exists).
[self dismissPopover:saveEditSender];
}