I have noticed strange behaviour.
When i'm presenting new viewController that is initiated programatically from different storyboard and flag animated is set to YES there is huge delay before ViewController is shown.
UINavigationController * enterVC = [[UIStoryboard storyboardWithName:#"Survey_iPhone" bundle:nil] instantiateViewControllerWithIdentifier:#"echoEntryVC"];
[self presentViewController:enterVC animated:NO completion:nil];
When flag is set to NO view Controller is presented immediately.
UINavigationController * enterVC = [[UIStoryboard storyboardWithName:#"Survey_iPhone" bundle:nil] instantiateViewControllerWithIdentifier:#"echoEntryVC"];
[self presentViewController:enterVC animated:YES completion:nil];
Does someone have the same problem? Any explanation would be good :)
Related
For my iPad version of the app I want to open my UIViewController as a UIPopoverController from the click of a button. So, the real code for view controller opening is below. How can I easily convert such code into opening a UIViewController as a UIPopoverController?
Code:
UIStoryboard *sb = [UIStoryboard storyboardWithName:[[NSBundle mainBundle].infoDictionary objectForKey:#"UIMainStoryboardFile"] bundle:[NSBundle mainBundle]];
UIViewController *aboutView = [sb instantiateViewControllerWithIdentifier:#"AboutViewController"];
aboutView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:aboutView animated:YES completion:NULL];
Use something like:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
UIPopoverController *poc = [[UIPopoverController alloc] initWithContentViewController:aboutView];
[poc presentPopoverFromRect:CGRectMake(somePoint.x, somePointY, 1.0, 1.0) inView:self.view permittedArrowDirections: UIPopoverArrowDirectionAny animated:YES];
} else {
aboutView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:aboutView animated:YES completion:NULL];
}
You can also present the popover from a button and you also can control the direction in which the popover will be presented. If you use UIPopoverArrowDirectionAny, iOS will make a smart decision for the popover to be visible.
You should also keep a strong reference to your popover and only present it while it is nil to make sure the popover is only present once. That means if the popover is dismissed, set the property holding it to nil.
A common solution is to have two storyboards, one for iPhone, one for iPad. That way you can use the popover segue in the iPad storyboard and the modal segue in the iPhone storyboard. You can readily arrange your Info.plist so that the correct storyboard loads automatically at launch time. You will still need some conditional code, though, since your code will respond differently to having a presented view controller than having a popover.
I have an ipad app.
I am trying to open view 2 (kind of push view) full with entire screen. how normally do with push view or UIModalPresentationFullScreen. but my base view which is view 1 is also modal view.
so i was trying to open view 2 when view 1 get dismiss…
- (void) handleNewButton :(int)id
{
[self dismissViewControllerAnimated:YES
completion:^{
NewViewController *View2 = [NewViewController alloc] init];
View2.modalPresentationStyle = UIModalPresentationFullScreen;
View2.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController: View2 animated:YES completion:nil];
}];
}
but my view 2 is not opening. i know i can not do push view. But is there any way to achieve it?.
When you do this dismissViewControllerAnimated the UIViewController (self in this case) is gone, in the sense that he is not on the screen anymore, if it has been released or not, that's another story. The reason for you to not be able to show the View2 (very poor name, it should at least ViewController2) is because you are trying to show it from a UIViewController that is not on the screen anymore.
So, what can you do?
The current self in the context of the handleNewButton method, in theory was presented by another UIViewController, that's from where you want to present your View2.
Probably the quickest way of implementing of what I said, would probably be with a notification described here. Although I would do it with a block, so when the self would be created, I would pass a dismissiCompletionBlock that would be called when that UIViewController was dismissed.
try to allocate NewViewController with nib name if you are not using storyboard,
[self dismissViewControllerAnimated:YES
completion:^{
NewViewController *n=[[NewViewController alloc]initWithNibName:#"NewViewController" bundle:nil];
View2.modalPresentationStyle = UIModalPresentationFullScreen;
View2.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController: View2 animated:YES completion:nil];
}];
or if you are using storyboard get NewViewController using identifier.
From one view(LoginTesteInicial) I can go to two tabBarControllers, but when I run the code, it crashes with this error:
Attempt to present <UITabBarController: 0x8a4a870> on <LoginTesteInicial: 0x8a46970> whose view is not in the window hierarchy!
here is my code from LoginTesteInicial.m:
UITabBarController *vc;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
vc = [[UIStoryboard storyboardWithName:#"Main_iPad" bundle:nil] instantiateViewControllerWithIdentifier:#"TabBarSemLogin"];
} else {
vc = [[UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil] instantiateViewControllerWithIdentifier:#"TabBarSemLogin"];
}
[vc setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[self presentViewController:vc animated:YES completion:nil];
The answer to your question is that when -viewDidLoad is called, the view controller's view is not in the view hierarchy. You need to wait until the view is placed into the view hierarchy. This can been done either in -viewWillAppear: or -viewDidAppear:.
The "Unbalanced calls to begin/end appearance transitions" warning you get is because a view controller has not be fully loaded before being replaced with another view controller. To avoid that warning, you can use -performSelector:withObject:afterDelay: to schedule the present view controller in the next run loop.
- (void)viewDidAppear:(BOOL)animated
{
…
[self performSelector:#selector(showTabBarController) withObject:nil afterDelay:0.0];
}
- (void)showTabBarController
{
UITabBarController *vc;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
vc = [[UIStoryboard storyboardWithName:#"Main_iPad" bundle:nil] instantiateViewControllerWithIdentifier:#"TabBarSemLogin"];
} else {
vc = [[UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil] instantiateViewControllerWithIdentifier:#"TabBarSemLogin"];
}
[vc setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[self presentViewController:vc animated:YES completion:nil];
}
Move [self presentViewController:vc animated:YES completion:nil] and related code it either of these
1 viewWillAppear
2 viewWillLayoutSubviews
3 viewDidLayoutSubviews
You will need to keep one flag which will take care that even if one of these method triggered multiple times your view will get presented only once.
Or you can avoid presenting view and add as subview, do this instead of presenting if you didn't like keeping flag etc.
[self.view addSubview:vc.view];
[self addChildViewController:vc];
[vc didMoveToParentViewController:self]
In my app i present a UINavigationController modally with a UIViewController as its rootViewController. I do it in form style. I added a second UIViewController which is also in form style and i can push to it fine. However when i perform a popViewController action after the second UIViewcontroller gets popped onto the first, the whole modally presented UIViewController gets dismissed. However i don't perform any dismissing and the dismissing function doesn't get triggered by accident either.
Any ideas why it's happening?
Sincerely,
Zoli
EDIT:
That's how i'm presenting the modal viewcontrollers with a navcontroller:
if(!welcomeScreenAlreadyPresented) {
welcomeScreenViewController = [[WAWelcomeViewController alloc]init];
}
welcomeScreenNavController = [[UINavigationController alloc]initWithRootViewController:welcomeScreenViewController];
[welcomeScreenNavController setModalTransitionStyle: UIModalTransitionStyleCrossDissolve];
[welcomeScreenNavController setModalPresentationStyle:UIModalPresentationFormSheet];
[welcomeScreenNavController setNavigationBarHidden:YES animated:NO];
[self.navigationController presentViewController:welcomeScreenNavController animated:YES completion:nil];
That's how i'm navigation in WAWelcomeViewController.m
registerViewController = [[WARegisterViewController alloc]init];
[self.navigationController pushViewController:registerViewController animated:YES];
And in WARegisterViewController.m that's how i pop back
[self.navigationController popViewControllerAnimated:YES];
What you need to do is put the viewController you want to push inside another UINavigationController.
registerViewController = [[WARegisterViewController alloc]init];
UINavigationController *modalNavigationController = [[UINavigationController alloc] initWithRootViewController:registerViewController]; // autorelease if you are not using ARC
[self presentViewController:navController animated:YES completion:^{}];
You might want to add the modalNavigationController as a property to later call popViewControllerAnimated: on it.
I am using storyboards, I have one viewcontroller and on click I need to show another view controller modally. I am trying using this code
[self presentViewController:zoomV animated:YES completion:NULL];
I am coming up with a blank screen.
This is how I create
zViewController *zoomV = [[zViewController alloc] init];
[self presentViewController:zoomV animated:YES completion:NULL];
I tried researching this and some answers revolve around using storyboards and not having a rootviewcontroller associated. So what I have is in the initial scene I have a navigationController, and from there I drag to another Viewcontroller a relationship which defines it as a rootViewcontroller. Is that sufficient ? or is this irrelevant?
Since you have your zViewController in your storyboard, you should instantiate your zViewController using UIStoryboard instantiateViewControllerWithIdentifier:.
In your first view controller, instead of creating the zViewController using alloc/init do this, of course setting an identifier for your zViewController in your storyboard.
zViewController *zoomV = [self.storyboard instantiateViewControllerWithIdentifier:#"yourIdentifier"];
[self presentViewController:zoomV
animated:YES
completion:NULL];
Also you could accomplish the same using a segue and executing it directly, without the need of instantiating the zViewController, but is up to you.
As a second(small) comment, do not name classes starting with lowercase in ObjC :).
You may refer below snippet for story board:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
AddNameViewController *sfvc = [storyboard instantiateViewControllerWithIdentifier:#"AddNameViewController.m"];
[sfvc setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentViewController:sfvc animated:YES completion:nil];