I have implemented the interactivePopGestureRecognizer. It transitions to the previous page. But the problem is that when the transition takes place, if there is a UIScrollView in the current view controller, it starts scrolling. Is there some way to prevent it?
I have added the gesture in my RootViewcontroller:
self.appNavController = [[UINavigationController alloc] initWithRootViewController:controller];
self.appNavController.interactivePopGestureRecognizer.enabled = YES;
self.appNavController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;
[self.appNavController setNavigationBarHidden:YES];
I call this in:
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
APP_DELEGATE.rootViewController.appNavController.interactivePopGestureRecognizer.enabled = NO;
}
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
APP_DELEGATE.rootViewController.appNavController.interactivePopGestureRecognizer.enabled = YES;
}
I found the solution. In the view controller which is being swiped i added the following:
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
self.scrollView.scrollEnabled = YES;
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
self.scrollView.scrollEnabled = NO;
}
It worked like a charm.
Related
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
return NO;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)])
{
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
self.navigationController.interactivePopGestureRecognizer.delegate = self;
}
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)])
{
[self.navigationController.interactivePopGestureRecognizer setEnabled:YES];
self.navigationController.interactivePopGestureRecognizer.delegate = nil;
}
}
//Am using this code but it not working in iOS 8.3 .Is there any problem in storyboard or it is not supported in iOS 8. Am irritating please give me a solution.
Create custom UIBarButtonItem and then set it in your navigation controller
self.navigationItem.leftBarButtonItem = customBarItem;
it might be helpful for you.
Add this 2 lines in the view controller's viewDidLoad method where you want to disable pop gesture
[self.navigationController.interactivePopGestureRecognizer setEnabled:NO];
self.navigationController.interactivePopGestureRecognizer.delegate = self;
I have a subclass of UIScrollView and I am trying to add it to my view. For some reason when I add it in the viewDidLoad it works as expected. But when I try adding it in the viewWillAppear then it seems to change the contentSize (although when I print the contentSize it is 905 in either case)
This works as expected:
- (void)viewDidLoad
{
[super viewDidLoad];
diptic = [[DipticView alloc] initWithFrame:self.view.frame];
diptic.item = self.item;
[self.view addSubview:diptic];
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
}
This cuts off the scrollView (both views are scrolled down all the way.)
- (void)viewDidLoad
{
[super viewDidLoad];
diptic = [[DipticView alloc] initWithFrame:self.view.frame];
diptic.item = self.item;
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.view addSubview:diptic];
}
Any ideas on why this might be happening?
EDIT:
I think the frame is being reset somewhere because if I do :
diptic = [[DipticView alloc] initWithFrame:CGRectMake(0, 0, 320, 200)];
I get the same results...
I write the codes below in my UIViewController that uses UINavigationController.
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.hidesBackButton = YES;
self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>) self;
}
I build and run my app,
self.navigationItem.hidesBackButton = YES;
above that works correctly, but
self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>) self;
that one DO NOT works.
So, I re-write the code below.
- (void)viewDidLoad {
UIBarButtonItem *backBarButton = [[UIBarButtonItem alloc] initWithCustomView:[[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 44.0f, 44.0f)]];
backBarButton.tintColor = [UIColor clearColor];
self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;
self.navigationItem.leftBarButtonItem = backBarButton;
}
It works correctly.
However, I want to use the first example.
The first one clearly express what I want to do.
Does someone have any idea?
In viewDidLoad, the view controller is not yet contained in a navigation controller, so the navigationController property is nil, which is why that line has no effect.
That said, assigning the delegate of UINavigationController's interactivePopGestureRecognizer is not good practice (I'm pretty sure it expects to be assigned to the navigation controller). Try disabling the gesture recognizer in viewWillAppear: instead:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
I watched the WWDC video on UIViewController Containment and read through this blog post: http://www.cocoanetics.com/2012/04/containing-viewcontrollers/
but I can't get my initial view controller to show. Is there something I am missing? In my ContainerViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
_homeViewController = [[HomeViewController alloc] init];
_detailViewController = [[DetailViewController alloc] init];
[self setSubViewControllers:#[_homeViewController, _detailViewController]];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (_selectedViewController.parentViewController == self) {
// nothing to do
return;
}
// adjust the frame to fit the container view
_selectedViewController.view.frame = _containerView.bounds;
// make sure that it resizes on rotation automatically
_selectedViewController.view.autoresizingMask = _containerView.autoresizingMask;
// add as child VC
[self addChildViewController:_selectedViewController];
// add it to container view, calls willMoveToParentViewController for us
[_containerView addSubview:_selectedViewController.view];
// notify that move is done
[_selectedViewController didMoveToParentViewController:self];
}
- (void)loadView {
// set up the base view
CGRect frame = [[UIScreen mainScreen] bounds];
UIView *aView = [[UIView alloc] initWithFrame:frame];
aView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
aView.backgroundColor = [UIColor blueColor];
// set up content view
_containerView = [[UIView alloc] initWithFrame:frame];
_containerView.backgroundColor = [UIColor grayColor];
_containerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[aView addSubview:_containerView];
self.view = aView;
}
- (void)setSubViewControllers:(NSArray *)subViewControllers {
_subViewControllers = [subViewControllers copy];
if (_selectedViewController) {
// remove previous VC
}
_selectedViewController = _subViewControllers[0];
}
My ContainerViewController is the initial view controller in my storyboard. I see that it shows on the simulator, but the HomeViewController (the first child view controller in my container) does not show.
When I step through the debugger, the subViewControllers property of my ContainerViewController does have the homeViewController and detailViewController in it. The viewDidLoad of HomeViewController also does get called. I just don't see anything on screen except the background color of the ContainerViewController.
Any thoughts? Thanks.
So I'm not the brightest person in the world, but the reason nothing was being shown on the screen was because the nibs were in the storyboard and I needed to do this instead:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPad" bundle:nil];
_homeViewController = [storyboard instantiateViewControllerWithIdentifier:#"HomeViewController"];
_detailViewController = [storyboard instantiateViewControllerWithIdentifier:#"DetailViewController"];
Hopefully this helps someone who is also not familiar with Storyboards yet.
You have an NSArray, but you are trying to access it as a C array.
_subViewControllers[0]
should be:
[_subViewControllers objectAtIndex:0];
That being said, you seem to have some code that could be better in other methods. I would personally clean this up a lot and make it much simpler. I would remove loadView and _containerView, and just use self.view as one normally would. For what you are trying to do, there really doesn't even seem a need to track parent and child view controllers. Anyway, this is how I would do it:
#interface ContainerViewController ()
#property (nonatomic, retain) NSArray *subViewControllers;
#end
#implementation ObservationReportViewController {
UIViewController *_selectedViewController;
}
#synthesize subViewControllers = _subViewControllers;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
HomeViewController *homeViewController = [[HomeViewController alloc] init];
homeViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
DetailViewController *detailViewController = [[DetailViewController alloc] init];
detailViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
// Retain the view controllers.
self.subViewControllers = #[homeViewController, detailViewController];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self setSelectedViewController: [_subViewControllers objectAtIndex:0]];
}
-(void)setSelectedViewController:(UIViewController *)selectedViewController {
if (_selectedViewController != selectedViewController) {
[_selectedViewController.view removeFromSuperview];
_selectedViewController = selectedViewController;
// adjust the frame to fit the container view
[self.view addSubview:_selectedViewController.view];
//_selectedViewController.view.frame = _containerView.bounds;
_selectedViewController.view.frame = self.view.bounds;
}
}
If you set the InitialViewController through the storyboard in a different storyb than the MainStoryboard, then you need to update the project settings to use that new storyboard.
Go to project settings, General and set the Main Interface setting to the new storyboard
This is amongst the oddest issues with iOS development I have ever seen. I'm relatively new to iOS development, so I apologize if I'm missing something obvious or my terminology isn't completely correct. If you need clarification, please let me know in the comments and I'll edit my question accordingly.
The Problem
I'm using Three20, so that might have something to do with it. But I have a "Home view" which is basically a series of images that link out to other views (shown in the image below). If I start our in portrait view, all is well.
The next view is a table view, shown below:
YAY! I can rotate and all is right with the world. BUT if I go back to that home view, rotate to landscape, and THEN go to this tabled view, the world breaks.
You'll see that there's a random space added to the right side of my table now. I don't know where and how it came from. Here's my Controller.m file:
#import "FriendTabsController.h"
#import "MyAppApp.h"
#import "JohnDoeManager.h"
#implementation FriendTabsController
#synthesize innerView, segmentedControl, innerController, friendsController, friendRequestsController;
- (void)addBottomGutter:(UIViewController*)controller {
if ([controller isKindOfClass:[TTTableViewController class]]) {
TTTableViewController* tableViewController = (TTTableViewController*)controller;
tableViewController.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0,0,50+44,0);
tableViewController.tableView.contentInset = UIEdgeInsetsMake(0,0,50+44,0);
}
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"Friends";
self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
self.navigationController.navigationBar.tintColor = nil;
friendsController = [[FriendsController alloc] init];
friendRequestsController = [[FriendsController alloc] init];
((FriendsController*)friendRequestsController).friendRequests = YES;
[self addBottomGutter:friendsController];
[self addBottomGutter:friendRequestsController];
innerController = friendsController;
[innerView addSubview:innerController.view];
[innerController viewDidLoad];
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
[self loadBannerAd:(orientation)];
}
-(void) loadBannerAd:(UIInterfaceOrientation)orientation{
MainLayer *mi = [MainLayer getInstance];
if (mi.useJohnDoeAds) {
[[JohnDoeManager sharedInstance] setCurrentViewController:self];
[mi.JohnDoeBanner.view removeFromSuperview];
if(orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
// This is a portait ad
if ([[MyAppUtils getCurrentDevice] isEqualToString:#"iphone"]) {
[mi.JohnDoeBanner setFrame:CGRectMake(0, 410-44, 320, 50)];
}else{
[mi.JohnDoeBanner setFrame:CGRectMake(0, 1024-44-90-20, 768, 90)];
}
} else {
// Landscape
if ([[MyAppUtils getCurrentDevice] isEqualToString:#"iphone"]) {
[mi.JohnDoeBanner setFrame:CGRectMake(0, 320-44-58, 410, 50)];
}else{
[mi.JohnDoeBanner setFrame:CGRectMake((1024-768)/2, 768-44-90-20, 768, 90)];
}
}
[self.view addSubview:mi.JohnDoeBanner.view];
[mi.JohnDoeBanner rollOver];
}
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[self loadBannerAd:(toInterfaceOrientation)];
}
- (IBAction)didChangeSegment:(UISegmentedControl *)control {
if (innerController) {
[innerController viewWillDisappear:NO];
[innerController.view removeFromSuperview];
[innerController viewDidDisappear:NO];
}
switch (control.selectedSegmentIndex) {
case 0:
innerController = friendsController;
self.title = #"Friends";
break;
case 1:
innerController = friendRequestsController;
self.title = #"Requests";
break;
}
[innerController viewWillAppear:NO];
[innerView addSubview:innerController.view];
[innerController viewDidAppear:NO];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[innerController viewWillAppear:animated];
self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
self.navigationController.navigationBar.tintColor = nil;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[innerController viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
[innerController viewWillDisappear:animated];
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
[innerController viewDidDisappear:animated];
[super viewDidDisappear:animated];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
[friendsController release], friendsController = nil;
[friendRequestsController release], friendRequestsController = nil;
[super viewDidUnload];
}
- (void)dealloc {
[super dealloc];
}
#end
So can someone please tell me what's going on? HELP!
You need to set wantsFullScreenLayout property to YES.
in your init methods set
self.wantsFullScreenLayout = YES;
This will solve your problem.