I am getting the error:
Application tried to present modally an active controller
when I attempt to run my code below.
I am wanting to present a modal view-controller that is embedded within a UINavigationController. I have the navigationVC instantiated before this point. I only get this error when I run this code a second time. What I mean is that if I click a button and it runs this code it will work properly. I can than modally close that view. If I click the same button again to run it once more, I am getting error.
- (void)pushToUserProfile
{
if (!self.profileVC) {
self.profileVC = [self.storyboard instantiateViewControllerWithIdentifier:#"profileVC"];
[self.profileVC setCanEditProfile:NO];
[self.profileVC setTitle:#"Profile"];
[self.profileVC setCanCloseModal:YES];
}
[self.navigationVC setViewControllers:#[self.profileVC]];
[self presentViewController:self.navigationVC animated:YES completion:nil];
}
What am I doing wrong below?:
edit:
I also run the code:
- (void)writeComment
{
if (!self.writeCommentVC) {
self.writeCommentVC = [self.storyboard instantiateViewControllerWithIdentifier:#"writeCommentVC"];
}
[self.navigationVC setViewControllers:#[self.writeCommentVC]];
[self presentViewController:self.navigationVC animated:YES completion:nil];
}
and it works with no issue. Not matter how many times I present/dismiss that view controller.
Related
I launch a modal view controller VCM embedded in a Navigation controller from VC1.
The modal VC has a button to go to another View Controller, VC2.
if the user presses the button to go to VC2, I need to simultaneously dismiss the modal and also change the sending from VC1 to VC2. (It's important to dismiss the modal to get rid of it, so I don't have VCs accumulating on the stack.)
Here is the action method in the modal attached to the VC2 button.
- (IBAction)VC2ButtonPressed:(id)sender {
[self dismissViewControllerAnimated:true completion:nil];
//Above line works fine
[VC1 performSegueWithIdentifier:#"showVC2" sender:VC1];//No known class method error
}
I can dismiss the modal without any problem (first line) but can't figure out how to simultaneously segue to VC2. There is a storyboard segue in VC1 named 'showVC2' for what it's worth. I do not have any relevant class methods currently in the sending VC. Should I create a special class method? Or how can I invoke a method in the VC that launched the modal.
Edit:
I also tried:
[self.presentingViewController performSegueWithIdentifier:#"showVC2" sender:self];
This compiles but gives runtime error () has no segue with identifier 'showVC2''
I think this is because VC2 is embedded in a tabbarcontroller.
Edit2:
I tried putting code in completion handler as suggested by #Oscar but while code gets fired, VC2 does not load
[self dismissViewControllerAnimated:YES completion:^{
[self gotoVC2];
}];
new method
-(void)gotoVC2 {
LogDebug(#"gotoVC2 called");//DOES log to console
UIStoryboard *storyBoard = self.storyboard;
IDFeedVC *VC2 =
[storyBoard instantiateViewControllerWithIdentifier:#"vc2"];
[self presentViewController:VC2 animated:YES completion: nil];
}
Thanks for any ideas.
When a logged in user opens my application, they are sent to the main TabBarController from my AppDelegate, like so:
UITabBarController *tabBar = (UITabBarController *)self.window.rootViewController;
tabBar.selectedIndex = 2;
// (this is MainViewController in the tab bar)
Now, the user is in MainViewController. When the user selects a particular chat they'd like to enter, they are sent to the ChatViewController (not on the TabBarController), like so:
[self performSegueWithIdentifier:#"showChatSeg" sender:self];
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.destinationViewController isKindOfClass:ChatViewController.class]){
ChatViewController *destinationViewController = (ChatViewController *)segue.destinationViewController;
if(self.createdDialog != nil){
destinationViewController.dialog = self.createdDialog;
self.createdDialog = nil;
}else{
QBChatDialog *dialog = [ChatService shared].dialogs[self.selectedChat];
destinationViewController.dialog = dialog;
}
}
}
When this happens, I see a spike in memory usage, which makes sense. However, when the user leaves the ChatViewController and return to the MainViewController, like so:
- (IBAction)backButton:(id)sender {
[self performSegueWithIdentifier:#"fromChatToDashSeg" sender:nil];
// This is a storyboard segue back to the MainTabBarController
}
I get the following warning:
Attempt to present <MainTabBarController: 0x17ef28d0> on <ChatViewController: 0x17d6c940> whose view is not in the window hierarchy!
And the memory usage remains the same. And when the user enters a chat again, the memory continues to increase. Am I not dismissing the sending view controllers properly?
What you are doing is not going "back" but rather, you are presenting a copy of the previous view on top of the one you already have. That's why memory is building up, because you just keep stacking more and more views on top of eachother. Assuming you are using a modal segue to present your chat view, try calling:
[self dismissViewControllerAnimated:YES completion:nil];
It's because you're trying to perform a segue just to get back to your original location. All you need to do is dismiss your current modal view controller by calling [self dismissViewControllerAnimated:YES completion:nil];. Whenever you add a modal view to the view stack you want to call this method to exit, unless your intent is to add yet another view on top of the modal.
im have two view controller UserListView and UserProfileView!
in UserListView view controller i'm have a button for swtich to UserProfileView and here is code.
UserListView.m - Click Action
- (IBAction)SettingClick:(id)sender
{
UserList *UserProfile = [self.storyboard instantiateViewControllerWithIdentifier:#"UserProfileView"];
[self presentViewController:UserProfile animated:YES completion:nil];
}
And code working fine, when user switch to profile (UserProfileView) have a close button back to UserListView and here is code.
UserProfileView.m - Close click action
- (IBAction)CloseClick:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
UserProfile *UseList = [self.storyboard instantiateViewControllerWithIdentifier:#"UserListView"];
[self presentViewController:UseList animated:YES completion:nil];
}
in this code i will using [self dismissViewControllerAnimated:YES completion:nil]; to close UserProfileView view controller for low ram usage and it work.
But affter i close UserProfileView i want to open this view controller again and it do not work, UserProfileView not showing again??
i using xcode 5 and building an App for ios 7, please help.
Thanks for your time.
If I understand correctly, when you call SettingClick: your app is displaying a UserList. So, when you dismiss a view controller presented on top of it, you should go back to UserList without the need for presenting it again. So you can try with:
- (IBAction)CloseClick:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
This will work unless you had originally presented UserList as well. In this case, UserList will be dismissed with the top controller. In this case, you can delay presenting a second time UserList after dismissing UserProfile, and it should work.
In the latter case, I would suggest you to use a navigation controller instead of simply presenting your controllers like you are doing. As you see, it is not really straightforward and you will get into catches of any kind. Presenting a controller works ok when you present just one controller at a time. On the other hand, if you instantiate a UINavigationController, this will handle the controllers' hierarchy for you.
use this -
- (IBAction)CloseClick:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
This will return to your previous view when u click that button that has been linked with this action
Using storyboards i have a tab bar controller with 2 views. In one view i want to have the ability to send the user in another view if is not logged in.
Show in the FirstView i have this:
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if(![self loggedin])
{
ErrorView *wizard = (ErrorView*)[[UIStoryboard storyboardWithName:#"Main_iphone" bundle:nil] instantiateViewControllerWithIdentifier:#"wizard"];
[wizard setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentViewController:wizard animated:NO completion:nil];
}
.....
If the user is not logged in i'am getting this error:
Warning: Attempt to present on whose view is not in the window hierarchy!
Any help will be very appreciable.
In viewWillAppear, the current view controller is not yet visible, hence why it says it will appear, not did appear. You can fix it by moving your code to the viewDidAppear method.
My app is a 5 tabviewcontroller app.
I want to build a first run set up routine that will collect info from the user in five steps (5 UIViews).
This GUI should hide my entire application GUI during the set up, in a similar way that happens when you restore an iPhone and have it set up for wi-fi, iCloud, etc...
I am trying
[self presentViewController:firstRunSetUp_1_ViewController animated:YES completion:NULL]
But this does not allow me to push the following view controllers.
UPDATE:
This is my code in appDidFinishLauching in appDelegate:
BHfirstRunSetUp_1_ViewController *f = [[BHfirstRunSetUp_1_ViewController alloc]init];
[self.myTabBarController.selectedViewController presentViewController:f animated:NO completion:NULL];
This is code inside "nextButtonClicked" IBAction, inside the BHfirstRunSetUp_1:
-(IBAction)nextButtonClicked:(id)sender
{
NSLog(#"inside nextButton clicked...");
// initialize second view controller:
if (firstRunSetUp_2_ViewController == nil) {
firstRunSetUp_2_ViewController = [[BHfirstRunSepUp_2_ViewController alloc]init];
}
[self.navigationController pushViewController:firstRunSetUp_2_ViewController animated:YES];
}
I have these lines in console:
2013-08-01 20:20:33.106 iNota[3245:907] inside nextButton clicked...
But the view isn't pushed!
Here is a screen shot:
http://www.idanfe.com/images/1.png "screenshot"
+++ UPDATE 2 ++++
I have taken Apple's Tabster example and changed it, adding my lines. You find a copy here:
http://www.idanfe.com/sample/Tabster.zip "Tabster"
Push a UINavigationController. eg:
UINavigationController * navigationController = [[UINavigationController alloc] initWithRootViewController:firstRunSetUp_1_ViewController];
[self presentViewController:navigationController animated:YES completion:NULL];
You can push them into section using as a modal view, but suggestion is to use uinavigationviewcontroller which is a rootviewcontroller in window ( in app delegate ).
If I understand what you're asking for, just present a navigation controller in the first step, which will show the root view controller of that navigate controller. Then push to your other 4 setup controllers. When you're done, dismiss the navigation controller.