Get current view - objective-c

I have an app which has split view inside a tab bar, and these split views often have navigation hierarchy and then sometimes modal views are presents on top of them, and it all works fine, but...
I am trying to display a passcode lock whenever the app goes into background, so I put
[self.window.rootViewController presentModalViewController:lockView animated:YES];
in my AppDelegate's method
- (void)applicationWillResignActive:(UIApplication *)application
...which works fine unless a modal view is displayed.
the passcode does not display if a modal view is open.
Is there a way to retrieve the currently active view controller so I can present this lock view?
Thanks in advance
Cheerio
Code that worked was as follows:
BOOL hasKids = YES;
UIViewController *topViewController = (UIViewController*)[[(UITabBarController*)self.window.rootViewController viewControllers] objectAtIndex:((UITabBarController*)self.window.rootViewController).selectedIndex];
while (hasKids) {
if (topViewController.presentedViewController) {
hasKids = YES;
topViewController = topViewController.presentedViewController;
} else {
hasKids = NO;
}
}
[topViewController presentModalViewController:lockView animated:YES];`

I think the easiest way is to keep track of which tab is currently active (there are a number of ways to do this, but I'd recommend implementing the UITabBarControllerDelegate and handling its tabBarController:didSelectViewController: method).
Once that's done, you'll probably need to manage a property in each view controller that holds any modal view controllers you present. If, however, you're on iOS 5 or higher, look into the UIViewController property presentedViewController. It appears that this is a new way to do exactly what you want.

Related

How do I know if a view is visible or not?

Say I have two view controllers: xVC and yVC. I have used the shake API and and have used the methods -(void)motionBegan,-(void)motionEnded: and -(void)motionCancelled in xVC. What happens is when the device is shaken, it fires a simple animation. Now the thing is that this animation is fired even when the I have yVC open that is, when yVS.view has been added as the subview. What I am looking for is some if condition which I can use in -(void)motionEnded: like this:
if(yVC == nil)
{
//trigger animation
}
By that I mean that the shake shouldn't work when yVC is visible. How do I do that? Please help.
The general advice I have seen and used is to ask a view if it has a non-nil window property:
if( ! yVC.view.window) {
// trigger animation
}
But note that this doesn't always equate with being visible; though in most apps it's about as good as you can performantly get (the basic case where it's not accurate is when a different view completely obscures it, but this may still satisfy your needs)
Add this to both of your view controllers:
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
visible = YES;
}
-(void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
visible = NO;
}
Now, just check the variable isVisible of both the view controllers and trigger your animation likewise.
The previous answers all work to some degree, but fail to take modally presented view controllers into account. If view controller A presents view controller B, of the previous answers will tell you that A is still visible. If you, like me, want to know whether or not the view is actually visible (and not just a part of the view hierarchy), I would suggest also checking the presentedViewController property:
if (self.isViewLoaded && [self.view window] && !self.presentedViewController) {
// User is looking at this view and nothing else
}
This works since presentedViewController will be non-nil whenever the current view controller OR any of its ancestors are currently presenting another view controller.

Reloading a view

I can't find the correct method on how to reload a modal view controller from within itself. I'm developing a very simple UI based app but I'm not sure how to do this.
I open the modal view with the following:
MainView *mainmview = [[MainView alloc] initWithNibName:#"submod" bundle:nil];
mainmview.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self mainmview animated:YES];
and then can dismiss it depending on iOS version. However this has no effect when used on what i need to be a simple restart button. Any help is appreciated.
You will have to implement your own "refresh" functionality - define a "refresh" method inside the modal view controller's class and do whatever needs to be done inside it - if for instance you have a tableview that requires a reload or to refresh your views depending on new data, etc...

Create a sort of navigation logic within an application: how to?

I have a number of view controllers that I want to navigate; however, I need to implement an intuitive way to move to previous ones. For the button press methods in my view controller custom classes to move forward, I do something like this:
NextViewController *next = [self.storyboard instantiateViewControllerWithId:#"NextViewController"];
[self presentModalViewController:next animated;YES];
With this in mind, how can I return back to previous views?
Why not just use the built in UINavigationController? You can hide the navigation bar and use custom controls to push and pop controllers as you wish
When using modals you simply add a button that links to the action:
-(void)goBack:(id)sender {
[self dismissModalViewControllerAnimated:YES];
}

Showing a different XIB/NIB in an iOS app

I have multiple nib (xib) files and I want the user to see a different one when they tap a button. What I am looking for:
- (IBAction)buttonTap {
//Code for showing a different nib goes here
}
I can't figure out how to do this. I can show a different view within the nib file just fine, but I can't get it to show a different nib. How do I show a different nib when the user taps a button?
Any help is appreciated! Thanks!
The way I handle switching between actual xib's, and I'm sure there are a multitude of ways to accomplish the same thing, is to have my App Delegate act as a routing center between my views.
I subscribe my App Delegate to recieve events from button presses for existing views. When it recieves a request to switch views, such as a button press, I do something like this:
- (void) showLogin
{
LoginViewController *loginViewController = [[LoginViewController alloc]
initWithNibName:#"LoginViewController" bundle:nil];
// Show
self.loginViewController = loginViewController;
[loginViewController release];
self.window.rootViewController = self.loginViewController;
}
I set my rootViewController to the view I am attempting to display. It doesn't release the old controller, but simply replaces the view being displayed. You can place more logic in to determine if it's already displayed, close out other views, etc. In most simplistic terms, this works for me.

Flip Animation in a navigation controller's view

i am testing all day on this but i can not get it to work.
I have my main App Delegate class with my MainWindow.xib.
In this main class i create my navigation controller and MainWindow points to my MainViewController.xib. In this MainViewController i have a simple tableview, where i push some views on the navigation stack.
Till here it's working great.
But i want the user to switch between two styles of presenting him data.
One is the tableview, and the other option is something like a map. Doesn't matter. Just 2 different Views. So i thought of using a button on my nav bar to flip between these two views.
Don't get this subview flip to work.
I tried it with that source but didn't get it to work.
Some hints would be great!
Suppose you have all the navBar, buttons ready. You can use modal view for the solution:
-(void)changeView{
//create some view
[youNewView setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[self presentModalViewController:youNewView animated:YES];
}
You can use the above method to flip to a new view.
-(void) dismissView{
[self dismissModalViewControllerAnimated:YES];
}
and use the second method in the new view to flip back.
I like this method a lot because you don't need to add any controller manually at all.