Access currently active displayed UIViewController - ios

I want to present a ModalView, everytime my application receives a Pushnotification.
On arrival of the Notification, my app displays any of the UIViewControllers within the app.
I need this UIViewController to call
[presentingViewController presentModalViewController:vc animated:YES];
// presentingViewController is what I need :)
Is there a way to find out which UIViewController is currently active?
I would know how to do this with e.g. UITabbarController or UINavigationController, but I can't rely on the presence of either of these.
I also tried getting the rootViewController via
[[[UIApplication sharedApplication] keyWindow] rootViewController]
and presenting the ModalView from there, but - of course - it wouldn't show for any other pushed/displayed views.

I think the easiest way would be to get a global variable of type id or UIViewController that you update every time you display a controller . This way you will always have a reference to the current controller.
Hope this helps.
Cheers!

Related

iOS Mail Composer without a UIViewController

My app runs some tasks in the background, then in the end shows an alert asking the user if she wants to send the result by email.
In other places of the app I use the MFMailComposeViewController in the same way as it should be (shown e.g. here). Here however, as I am in the completion block of a potentially long running task, I have no reference to a UIViewController instance I could use for the following calls:
...
mailSendingController.mailComposeDelegate = self;
[self presentModalViewController:mailSendingController animated:YES];
I could probably keep the reference to the VC that invoked the task, but it might be dismissed before the task finishes.
What can I do? Create a fake hidden VC just to serve as the basis of the MFMailComposeViewController? Is there a way to show MFMailComposeViewController without an underlying VC? Use somehow the VC that is currently on top of the stack?...
Any ideas are welcome.
First of all, presentModalViewController:animated: is deprecated as of iOS6 [1] you should use presentViewController:animated:completion: [2]
I would just get the app's root view controller and then use that to present the modal view controller. That way it will be on top no matter what and you know the root view controller is always there.
Look at this question for some hints on accessing the app's root view controller.
Also, if you are going to do GUI stuff make sure you go back to the main thread:
dispatch_async(dispatch_get_main_queue(), ^{
// Present the VC here
});
Good luck!
use ]
[UIApplication sharedApplication].keyWindow.rootViewController presentViewController: mailSendingController]

UIViewController incorectly shows on its side

I have two views, when that app loads if the prefs match the users log in I am trying to load the next ViewController immediatly.
Each view normally shows in landscape and I have set the apps settings to only allow landscape. However when I try to load the second view immediatly from the first view "viewdidload" The second view appears on its side.
This is what my code looks like, this code is in a method that gets called from the first viewcontrollers viewdidload
currentProjectListViewController = [[CurrentProjectListViewController alloc] initWithNibName:#"CurrentProjectListViewController" bundle:nil];
[currentProjectListViewController setDelegate:self]; // set the delegate so it can access the returning method to update the view
UIWindow* keyWindow= [[UIApplication sharedApplication] keyWindow];
[keyWindow addSubview: currentProjectListViewController.view];
[self presentViewController:currentProjectListViewController animated:NO completion:nil];
I have no idea where to even start with this. it makes it to the second views viewdidload how ever like I say the view appears to be correct but its just on its side effectivly 90degrees incorrect.
any help making sure this apperar in landscape would be greatly appreciated.
I think your View hierarchy is somewhat wrong.
Why are you adding view of currentProjectListViewController to UIWindow object and immediately after adding it as subview you are presenting it using presentViewController from the current ViewController?
When you load and show the second ViewController, your presentViewController code should work.
You dont need to play with your UIWIndow object. Just make sure you dismiss your present view controller so as to reduce memory footprint and memory leaks.

Passing data to the view controller that UINavigationController points to

So heres my question. I am a silent stackoverflow skimmer and Im using xcode 4.5 storyboards for an application which starts with a view controller which asks for the username and password. My application checks data via a backend server and then if the login is correct it performs a segue which points to the uinavigationcontroller which forwards the screen to the main menu.... The uinavigationcontroller hasnt been tampered with and pushes the mainmenu automatically.
Login_screen -> UINavigationController -> Main_Menu
My question is how do i pass the NSString username from the login screen to the main menu screen.
I understand how to pass data from one screen to the next when the segue is pointing directly to it via the prepareforsegue method as well as performsegue. But in this case the login_screen segue points to the uinaviationcontroller which points to the main_menu controller
My assumption is that i will need to make a custom class which inherits UINavigationController and implement certain methods but since uinavigationcontroller isnt seen i dont think viewdidload or viewwillappear are the right methods.
Any help will be appreciated
I am a new user so i am not allowed to post images but i will fix that as soon as possible
You can use the topViewController property of the UINavigationController.
Cast the UINavigationController.topViewController object to Main_MenuViewController and set the data normally.
Hope this helps
in whatever case you need some container to persist the current selected/active object. I f for whatever reason you can't extend the UINavigationController (I'd wonder why), you can always have some property in AppDelegate you can assign and in your final Main_Menu controller read this property.
Smth like this:
AppDelegate* app = (AppDelegate*)[[UIApplication sharedApplication] delegate];
NSObject* myThing = app.myObj
if(!myThing) {
app.myObj = ...
}

IOS 5 Opening a specific ViewController from the AppDelegate

I am really new to IOS so I apologize if this questions is not worded clearly. I have tried searching around but I have not found exactly what I am looking for.
basically in my AppDelegate applicationDidBecomeActive method, I am making a call to my webservice to make sure that the user is still a valid user, and to pull down some refrehsed data, or kick them back to the login page if they are no longer valid.
The part that I am having trouble with is the second part. How can I load and show and specific ViewController(in this case the loginViewController) when the user is found to be invalid? I want to let the normal viewController flow happen when they are valid, which is is doing fine, but I can not figure out how to launch a specific viewController when I need to from AppDelegate.
Any ideas?
I think I got it! I used this code in the AppDelegate to display the ViewController I needed.
UIViewController *loginController = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
UINavigationController *loginNavController = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"LoginNavController"];
UIViewController *currentVC = self.window.rootViewController;
_window.rootViewController = loginNavController;
[currentVC presentViewController:loginNavController animated:NO completion:nil];
For simplicity, lets say you have a one view app (not nav controller, not tab bar controller - the solution scales but easier to explain). When you get the appDelegate message that the app launched, then make a UIImageView the root view and show your launch image (user thinks you are still booting up). Try to log in, and do this in some other object (not a view controller). If you succeed, you make your desired view the rootView, and users sees it. If the login fails, then you makea login window the rootView. The key here is to have an object that is driving this and can interact with the appDelegate. You could also add this functionality to the appDelegate itself.

Navigate to Root ViewController From Modal

I have a root view controller (RVC) that opens up a Modal ViewController (MVC). I then navigate within the MVC to few more VC's via a push. What is the best practice to get from one of those VC's back to the RVC?
Normally I have a delegate from the Modal VC that calls up to the RVC which then dismisses the modal, but if you navigate away from it, but I'm not sure how I would do that if you navigate away from it.
Without seeing any code it is a bit hard to help but let me shoot in the dark here.
I will assume that the first controller presented inside the modal view provides the protocol/delegate to call the dismiss action.
If you use UINavigationController inside your modal view to push other view controllers on the stack you can always obtain the first controller like this
UIViewController * yourFirstController = [[[self navigationController] viewControllers] objectAtIndex:0];
// and then use your delegate to call your dismiss method
// you will need to typecast your controller based on your subclass otherwise will get warning here
if ([[yourFirstController delegate] respondsToSelector:#selector(yourCloseProtocolMethod)]) {
[[yourFirstController delegate] yourCloseProtocolMethod];
}
Don't forget that a delegate doesn't have to be a property of a UIViewController inside your model navigation stack. Consider creating a singleton class that holds a reference to the rootviewcontroller as a delegate. That way any class in your application has access to it and you aren't forced to continually pass it through to every UIViewController that requires it.

Resources