I am using an UIActivityViewController. When the user sends my application to the background on the iPhone (when they press the home button, etc) I need to remove the spawned UIActivityViewController and any children that may have come from it. This is to say that if the user selects the "Mail" or "Message" option on the UIActivityViewController I need to remove the view (view controller?) that spawns as a result of this action.
I have tried the following code by found that it only removes the original UIActivityViewController and none of the additional views it spawned.
[_myActivityController dismissViewControllerAnimated:NO completion:nil];
Try this in your appDelegate applicationDidEnterBackground. Dismiss the top most view controller which is presented. Hope this will help you out.
- (void)applicationDidEnterBackground:(UIApplication *)application {
UIViewController *mytopController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (mytopController.presentedViewController)
{
mytopController = mytopController.presentedViewController;
[mytopController dismissViewControllerAnimated:NO completion:nil];
}
}
Related
Let say I have view controllers named A,B,C,D,E I open theseViewConrollersone after the other in presentModel way. When I am in ViewController E I want to open another ViewController F in presentModel way. In that F ViewController I have a back button. When I click on that It should dismiss the F and show the A ViewController. But now when it dismissse shows E. How can I dismiss all other viewcontrollers except the A when I click the back button of F
Please help me. Thanks
UPDATED
-(IBAction)dismisthis:(id)sender{
UIViewController *dismissingViewController = self.presentingViewController;
while (dismissingViewController.presentingViewController != nil && [dismissingViewController isKindOfClass:[FrontViewController class]]) {
dismissingViewController = self.presentingViewController;
}
[dismissingViewController dismissViewControllerAnimated:NO completion:NULL];
If you dismiss a view controller that is presenting another view controller, the entire hierarchy is dismissed. It doesn't matter how many levels there are. So all you have to do is find your view controller A and tell it to dismiss its presented view controller.
If A is always the bottom of the heap, you can use a simple loop to find it:
UIViewController *dismissingViewController = self.presentingViewController;
while (dismissingViewController.presentingViewController != nil) {
dismissingViewController = self.presentingViewController;
}
[dismissingViewController dismissViewControllerAnimated:YES
completion:NULL];
What about sending Notification using NSNotificationCenter from F and A will listen to it. Once A receives the notification, it will call dismissViewController which I think will dismiss all.
At this moment i can think of three solutions
You should keep track of all viewControllers in a stackObject(which is an array) in Appdelegate. When you want it access this get these array and dismiss all view controler objetcs.
Each viewcontroller you can observer for a NSNotification which will listen for notification. When you need it in "F" just post the notification and this notification will dismiss the eviewcontrollers
Go for NavigationController so that you can push to rootviewcontroller
Try this:
UIViewController *rootVC = [UIApplication sharedApplication].delegate.window.rootViewController;
[rootVC dismissViewControllerAnimated:YES completion:nil];
// One-liner
// [[UIApplication sharedApplication].delegate.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
Make A as rootViewController and use below code on Back button of "F":
[[[[UIApplication sharedApplication] keyWindow] rootViewController] dismissViewControllerAnimated:true completion:nil];
I'm a bit lost trying to figure it out...
I have a tab bar based app with login screen at the start. Login screen should be done as Modal View Controller BEFORE tab bar controller appears.
The problem is that I can present it only in viewDidAppear: method of TabBarController. And user can see for half a second content of the UITabBarController. I've tried to move call to viewDidLoad: or viewWillAppear: but it logs an error in console: "whose view is not in the window hierarchy!". As far as I can understand you can only add ModalViewController when all child UIViewControllers of UITabBarController are loaded, ad that happens in viewDidAppear: delegate method.
Do you have any solution how to show login screen without showing TabBarController before?
I've tried 2 ways of displaying ModalViewController, both of them work in viewDidAppear: only
XIB file with login view and using presentViewController: code
self.loginController = [[LoginViewController alloc] init];
[self presentViewController:self.loginController animated:NO completion:nil];
Storyboard, modal segue and calling it from the code:
[self performSegueWithIdentifier:#"loginScreen" sender:self];
Instead of a modal, you might consider pushing the login screen onto a navigation stack. Inside viewWillAppear: you can just instantiate your login viewController and push it. You could also do it in viewDidLoad if you'd like.
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.navigationController pushViewController:yourInstantiatedLoginViewController animated:NO];
}
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
My app basically has two view controllers, starting in a navigation controller:
1) MainViewController, which asks user to pick Camera or Album and then presents UIImagePicker
2) PhotoViewController, which receives photo.
However, in the second VC, when the user hits "Back", I would prefer to immediately return to either the Camera or Album they selected, rather than MainVC and then reloading the picker.
Should I separate an entirely new ViewController dedicated to the ImagePicker rather than presenting it within MainViewController? Using pushViewController: doesn't work as 'Pushing a navigation controller is not supported' perhaps meaning that imagePickers are nav controllers too.
MainViewController currently displays it like this:
[self.navigationController presentViewController:self.imagePicker animated:YES completion:nil];
Any suggestions appreciated, thanks.
A simple solution could be inside your MainVC have 2 bool values calledCamera, calledLibrary
when you create your new VC you set the one you choose your pic from to YES. So when you come back...
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (calledCamera){
//call cameraPicker to load before de MainVc shows
}
if (calledLibrary){
//call the LibraryPicker before...
}
}
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.