How to call one controller from two separate button clicks - ios

I have view controller I want to load different web pages on button clicks.
I have single view controller where i can load web page.
Button click events
- (IBAction)btnResortTVTouch:(id)sender {
GlobalWebViewController *globalWebViewController1 = [[GlobalWebViewController alloc] init];
globalWebViewController1.strUrlName = #"http://www.youtube.com/user/xyz";
[self presentViewController:globalWebViewController1 animated:YES completion:nil];
[globalWebViewController1 selectPageLink];
}
- (IBAction)btnPIntrestTouch:(id)sender {
GlobalWebViewController *globalWebViewController = [[GlobalWebViewController alloc] init];
globalWebViewController.strUrlName = #"http://www.pinterest.com/xyz/";
[self presentViewController:globalWebViewController animated:YES completion:nil];
[globalWebViewController selectPageLink];
}
It gives error
2013-12-19 03:00:17.885 RWNewYork[5941:907] Warning: Attempt to present GlobalWebViewController: 0x80c8e90 on FiveViewController: 0x81af490 which is already presenting GlobalWebViewController: 0x80826e0

You probably copied the first button, that is how you created the second one in the storyboard, and now it has 2 separate actions. So for one of your buttons both methods are called. Right-click on them in the storyboard and you can see the actions attached.
Edit:
Maybe you should call the selectPageLink method from the completion block of the presentation.

It's telling you that you've already presented a GlobalWebViewController from your FiveViewController, and you're trying to present another GlobalWebViewController from it as well, which isn't possible. So your button press must be somehow calling both methods, or calling one of them twice.

Related

Switch between ViewControllers using a button?

I am very new to programming, especially iOS, so any answer should be given as if I am a baby with ADHD.
This is what I have in my buttonclick:
ItemCreateViewController *itemCreateViewConrtoller = [[ItemCreateViewController alloc] init];
[[self navigationController] pushViewController:itemCreateViewConrtoller animated:YES];
What am I missing?
There are a lot of reasons why this could be happening among which is your button is not triggering the intended action. Among the reason why a button could not trigger is your XIB button is not connected to the button object defined in your header and method file.
If you look at the .h file look at all your IBOutlet items there should be a circle on the left most column if it is darkened out it is connected other wise it is not, and you need to connect this in your XIB file.
If this is not the problem please display the code where you specify the selector it should be something like this:
[cancel_button addTarget:self action:#selector(Cancel:) forControlEvents:UIControlEventTouchUpInside];
Make sure that the selector is an IBAction function -
-(IBAction)Cancel:(id)sender {
[self dismissViewControllerAnimated:YES completion:NULL];
return;
}
One other thing, any statement after pushViewController will get executed prior to any actual change in the view. The actual View change only happens once control is returned to IOS. This is significant if your push view controller command is within a long conditional process and you fail to code the return / exit properly.
Since you are using a XIB file for your second view, you need to create it as follows -
ItemCreateViewController *itemCreateViewConrtoller = [[ItemCreateViewController alloc] initWithNibName:#"ItemCreateViewController" bundle:nil]; //Ensure you use correct nib file name
Then you can push it
[[self navigationController] pushViewController:itemCreateViewConrtoller animated:YES];
But since you are using a Storyboard you could have just added the new view to your storyboard, linked the button to the new view with a "push" segue and everything would have been done for you.

start 1 view controller 2 buttons that lead to 2 different view controllers

I have the first ViewController that has 2 buttons on it. One to go to ViewController1 when clicked and the other to go to ViewController2 when clicked. When i click the first button it takes me to ViewController1 but when i click the second button it goes to a black screen and gives the warning:
Warning: Attempt to present on while a presentation is in progress!
What am I doing wrong?
Here is my code:
-(IBAction)goToYourClosetViewController: (id)sender{
YourClosetViewController *closet = [[YourClosetViewController alloc] initWithNibName:nil bundle:nil];
[self presentViewController:closet animated:YES completion:NULL];
}
-(IBAction)goToPlanOutfitViewController: (id)sender{
PlanOutfitViewController *planOutfit = [[PlanOutfitViewController alloc] initWithNibName:nil bundle:nil];
[self presentViewController:planOutfit animated:YES completion:NULL];
}
Are you pressing the first button and then the second button in rapid succession by any chance?
If that's it then you need to disable your buttons while the modal presentation is in progress, and re-enable them in your completion blocks.
If not, then how are you displaying the first view controller? (The one that contains these 2 buttons)
You are probably trying open the second view controller before you close the first view controller. That's the kind of error message in such cases.
When you go back to your initial view controller from either first or second view controller, do this:
[FirstViewControllerInstance dismissModalViewControllerAnimated:YES];

UINavigationController: presenting view controller while dismissing another controller is in progress on iPad

I have a view that requires user to be logged in. When the user attempts to open that view an he is not logged in I will call the login view for him to login and after he is done I will call the original view that he intended to see.
On iPhone this works fine as I push view controllers there.
But on iPad where I present view controller this does not work. It says that dismissal in progress, can't show new controller. Here is the code:
- (void) buttonPressed
{
if (!userLoggedIn) { // userLoggedIn getter calls new screens of login if needed
return; // this is executed if user declined to login
}
MyViewController *temp = [[MyViewController alloc] init];
[self.navigationController presentViewController:temp animated:YES]; // this returns warning that dismissal in progress and does not work
}
What can I do about that? On iPhone all of my logic works fine, but on iPad it fails. I use it in many places and completely rewriting code is not good.
EDIT: more code:
- (BOOL) userLoggedIn {
// code omitted
[centerController presentViewController:navController animated:YES completion:nil];
// code omitted
[centerController dismissViewController:navController animated:YES]; // setting to NO does not fix my problem
return YES;
}
EDIT2:
This is the code for iPad. I have removed iPhone-related code. What it does on iPhone - instead of presenting controller it uses pushing, and in that situation everything works fine.
You cannot present another view as long as the dismissing of your 1st view is not complete. The animation of dismissing view should be completed before presenting new view. So, either you can set its animation to NO while dismissing, or use
performSelector:withObject:afterDelay:
and present the next view after 2-3 seconds.
Hope this helps.
You've not posted enough code to really see what you're doing, but one approach to the problem of dismissing and pushing view controllers clashing in this way is to make a the pop+posh into a single atomic operation operation, rather then seqential operations.
You can do this by using the setViewControllers:animated: method on UINavigationController. This allows you to effectively remove one or more view controllers, and add one or more view controllers, all as one cohesive operation, with one seamless animation.
Here's a simple example:
[self.navigationController pushViewController:loginController];
// ... later on, when user login is validated:
NSMutableArray *viewControllers =
[self.navigationController.viewControllers copy];
[viewControllers removeLastObject];
[viewControllers addObject:[[MyNewViewController alloc] init]];
[self.navigationController setViewControllers:viewControllers animated:YES];
If you do things this way, your code will be more predictable, and will work across iPhone and iPad.
For more info, see the API docs.
Update
Since your problem involves a modal dialog on top, try using setViewControllers:animated:NO to change the nav controller stack underneath the modal login dialog before you dismiss the modal.

iOS: Pushing a view controller with animation only works once

I am creating an iPhone client for one of my apps that has an API. I am using the GTMOAuth2 library for authentication. The library takes care of opening a web view for me with the correct url. However I have to push the view controller myself. Let me show you some code to make things more clear:
- (void)signInWithCatapult
{
[self signOut];
GTMOAuth2ViewControllerTouch *viewController;
viewController = [[GTMOAuth2ViewControllerTouch alloc] initWithAuthentication:[_account catapultAuthenticaiton]
authorizationURL:[NSURL URLWithString:kCatapultAuthURL]
keychainItemName:kCatapultKeychainItemName
delegate:self
finishedSelector:#selector(viewController:finishedWithAuth:error:)];
[self.navigationController pushViewController:viewController animated:YES];
}
I have a "plus"/"add" button that I add to the view dynamically and that points to that method:
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(signInWithCatapult)];
When I press the "add" button, what is supposed to happen is to open the web view with an animation, and then add an account to the accounts instance variable which populates the table view. This works fine if I add one account, but as soon as I try to add a second account, the screen goes black and two errors appear in the console:
nested pop animation can result in corrupted navigation bar
Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
The only way that I found to avoid this problem was to disable animations when pushing the view controller.
What am I doing wrong please?
Typical situations
You push or pop controllers inside viewWillAppear: or similar methods.
You override viewWillAppear: (or similar methods) but you are not calling [super viewWillAppear:].
You are starting two animations at the same time, e.g. running an animated pop and then immediately running an animated push. The animations then collide. In this case, using [UINavigationController setViewControllers:animated:] must be used.
Have you tried the following for dismissing once you're in?
[self dismissViewControllerAnimated:YES completion:nil];
I got the nested pop animation can result in corrupted navigation bar message when I was trying to pop a view controller before it had appeared. Override viewDidAppear to set a flag in your UIViewController subclass indicating that the view has appeared (remember to call [super viewDidAppear] as well). Test that flag before you pop the controller. If the view hasn't appeared yet, you may want to set another flag indicating that you need to immediately pop the view controller, from within viewDidAppear, as soon as it has appeared. Like so:
#interface MyViewController : UIViewController {
bool didAppear, needToPop;
}
...and in the #implementation...
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
didAppear = YES;
if (needToPop)
[self.navigationController popViewControllerAnimated:YES];
}
- (void)myCrucialBackgroundTask {
// this task was presumably initiated when view was created or loaded....
...
if (myTaskFailed) { // o noes!
if (didAppear)
[self.navigationController popViewControllerAnimated:YES];
else
needToPop = YES;
}
}
The duplicated popViewControllerAnimated call is a bit ugly, but the only way I could get this to work in my currently-tired state.

Displaying the right UIView when dismissModalViewControllerAnimated:completion: is called

Let me explain. I have multiple UIViewControllers. On my MainPageController, I have 3 UIViews. Let's enumerate it this way: the first UIView is called LoginView, the second is called HomeView and the other one is called RegView. Now in HomeView, there are multiple buttons that will lead to other UIViewControllers. For example, one button will lead to StoreController. Now if I am inside StoreController and I want to go back to MainPageController, I simply call:
[self dismissModalViewControllerAnimated:YES completion:nil]
This will send me back to the HomeView.
That is good. However, inside the StoreController, there are buttons which will supposedly direct me to LoginView or RegView, whichever button was tapped. The problem is when the method [self dismissModalViewControllerAnimated:YES completion:nil], it only take me back to HomeView, no matter which button I pressed.
So how will I display the right UIView once the dismissModalViewControllerAnimated is called?
EDIT:
This is how I show the UIViews:
-(void)viewDidLoad
{
//Initialize the views here...
}
-(void)showViewByTag:(NSInteger)tag
{
if (tag == 1)
{
[self.view addSubview:loginView];
}
else if (tag == 2)
{
[self.view addSubview:homeView];
}
else
{
[self.view addSubview:regView];
}
}
Now I call the method showViewByTag: somewhere in my code to display the views.
What you could try and do is following: before calling [self dismissModalViewControllerAnimated:YES completion:nil] (and thus go back to your home view), change the view currently displayed in your MainPageController:
[(MainPageController*)self.presentingViewController showViewByTag:desiredViewTag];
[self dismissModalViewControllerAnimated:YES...];
If you are worried at the cast and you foresee that self.presentingViewController might be not of MainPageController type on some occasions, then you can check explicitly for its type:
if ([self.presentingViewController isKindOf:[MainPageController class]])
[(MainPageController*)self.presentingViewController showViewByTag:desiredViewTag];
[self dismissModalViewControllerAnimated:YES...];
For this to compile, MainPageController.h must be imported in your modal controller class.
dismissModalViewController will always bring back the viewController which presented it ,and that can be only one,so the ideal way would be to tell the navigationController to initWith your desired viewController..
eg on regButton click in the presented modalview
RegViewController *regViewController = [[RegViewController alloc]initWithNibNam:#"RegViewController" bundle:nil];
[self.navigationController initWithRootViewController:regViewController];

Resources