I have a problem. I am working on an app which is tab bar based app. In this app, we call [self.view addSubview:newVC.view] when we want to navigate to a new view. newVC is the view controller of the new view that we want to display. Also we use [self.view removeFromSuperview] when we want to go back to previous view.
So in other words, there is no navigation controller. Now problem is that I want to update the previous view. Since we are using [self.view removeFromSuperview], viewDidAppear of the previous view is not get called and so we have no way of refreshing that view.
I know the approach that we used has flaw but since its a large scale app and changing it to implement navigation controller with take lot of time so I need you to please help me find the solution of this problem. How can I call the viewDidLoad or viewDidAppear or the previous view on calling [self.view removeFromSuperview] from its subview?
Yes, as Sarah said you should hold a reference to previous controller in "stack".
And when "poping" controller from stack, call appropriate method on previous controller.
Certainly you should not call viewDidLoad (it is not called when you pop controller from navigation stack of real UINavigationController).
You can call viewWillAppear or viewDidAppear, but better use your own method, like viewRevealed (you can also call it from viewWillAppear or viewDidAppear). It is useful to make
base class where implement all this functionality and derive all you controller from the base class. It may look like:
- (void) pushViewController:(BaseViewController *)baseController{
[self.view addSubview:baseController.view];
baseController.parentController = self;
}
- (void) pop{
[self.view removeFromSuperview];
[self.parentController viewRevealed];
}
viewDidLoad method call only when when you jump into a controller through pushViewController method. If you call removeFromSupreView, it will call viewWillAppear method. Here if you want to navigate from one view to another view over tabbar you must use UINavigationController in Mainwindow.xib and connect its viewController with App delegate.
Related
Let's say I have a viewcontroller "ViewBViewController". In that viewcontroller I create an instance of the "ViewAViewController" and use the addSubView: method to display this ViewAViewController. It then processes a bunch of information, and is now done. I want it to automatically get removed as a subview when it's done.
I was looking at the removeFromSuperview method, but can't seem to call that from within the viewcontroller whose view I'm trying to remove (my first instinct was [self.view removeFromSuperview], but that gets rid of the entire view, not just the subview I'm after).
The only way I can think of is setting up a delegate protocol, and have View B take care of the unloading of View A on behalf of View A as its delegate. However this approach seems a bit overkill. Am I missing an easier solution?
Thanks in advance!
UIViewController does not respond to removeFromSuperview, because a UIViewController is not a UIView but a UIViewController. No surprises there. You can call removeSuperview on any view, such as the view associated to a view controller (here self):
[self.view removeFromSuperview];
or if you just want to remove one subview:
[mySubview removeFromSuperview];
or if your subview is a member of self (i.e. declared in the interface say):
[self.mySubview removeFromSuperview];
Have you tried: setHidden: YES ?
There are two basically correct solutions here:
Use a navigation controller. You can hide the navigation bar if you don't want it to be part of your interface. Then you can dispose of the top view controller and its view from either view controller by calling
// argument can be YES or NO, as you like
[self.navigationController popViewControllerAnimated:YES];
Use a delegate call that tells the parent view controller to do something like
-(void)removeViewA {
// remove the view from the view hierarchy
[self.viewAController.view removeFromSuperview];
// dispose of the view controller so it doesn't leak.
self.viewAController = nil;
}
It's important to make sure that you don't leak the child view controller and its view.
Either of these approaches works, but using a navigation controller seems more idiomatic to me.
i'm working in view-based template,
and I have main.m, which I haven't touched.
and one view controller which is my current display,
and one dummy controller which has nothing.
If I implement the dummy controller, and want to switch between
two view controllers, where and how should I do it?
I've only worked with subviews,
but not quite sure where to touch the view controllers...
does it work the same as addView, release as with subviews?
Please help me out..
It depends on how you want you're looking to do. You could present your dummy view controller either modally or non-modally. To do it modally, check out:
- (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated
Here is a sample on how you would do something like that:
DummyViewController *dummyController = [[DummyViewController alloc] init];
[self presentModalViewController: dummyController];
You could also do something like:
- (void)presentFlipSideViewController:(UIViewController *)flipsideViewController
You would call these methods when the user did something, such as tap a button. Both of these methods would be implemented in the view controller handling the tap or action, in your case, the project template view controller .
Here's the scenario, switchViewController is the view added to the main window. So switchViewController is the main view, so if I want to go view B, I will addsubview of view B, there isn't a need to remove switchViewController's view right?
The issue is after I go back from view B to switchViewController's view, the method viewWillAppear is not being called anymore.
Why is it so?
viewWillAppear: is not called automatically when a view is removed from or added to the view hierarchy. It is the responsibility of the view controller to call it at the right time. The built-in view controller classes do this whenever you present or push a new view controller. Since you do not use this mechanism in your app, the method doesn't get called (unless you call it yourself).
That's because it never disappeared, you were just putting something else in front of it. If you want to navigate from one screen to another and back, they should be separate view controllers, and you should be using UINavigationController and its pushViewController:isAnimated: method.
It's not getting called beause your just modifying the first view, not navigating to a different one.
You might consider embedding your view in a Navigation controller, then calling your ViewB with
[navigationController pushViewController:viewB animated:YES];
When we click on the back button on a nav view, is there any method (delegate) which gets called on current view controller before poping it out of stack and pushing next in stack?
The only method available is the viewWillDisappear and the viewDidDisappear in the viewController managed by the UINavigationController. You might be able to check the size of the UINavigationController viewController array property and compare it with the last known -count. If there are more controllers in the stack, you know that something was pushed. If there are less, something was popped.
You can hook up your own -back:(id)sender method as the selector for your back button and then do what ever you want inside that method, as long as you call:
[[self navigationController] popViewControllerAnimated:YES];
i have an app that uses a navbar. What i want to acomplish is make it transparent when i push in the last view from the nav sequence, and make it opaque when i click the back button on the nav
i tried with on dealoc, but it doesn't work. My view is an UIScrollView not an UiView, but i guess that makes no difference.
As i see it, eighter i have to control the events on the nav bar, and see the type of the view with a loop or trigger some event on the "unloading" of my current view
when i push in the view i do a
self.navigationController.navigationBar.barStyle = UIBarStyleBlackTranslucent;
and when it pops out i need the
self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
Pushing and popping a view with UINavigationController or UITabController will call the view
{Will,Did}{Appear,Disappear} methods so I think you need to hook into the child view's ViewWillDisappear.
I'd architect it so that top level navigation controller sets itself as the childs delegate, and the child calls its delgate with an "I'm unloading" type function where you change the navbar style.
Actually the best way for this is to use UINavigationControllerDelegate. I extended UINAvigationController and set the delegate to self and used one of the methods of the UINavigationControllerDelegate protocol.
You can't really depend on dealloc to ever get called, much less when you want it. That should only be used to release retained objects.
I think you should be able to add the barStyle changes in the viewDidAppear and viewDidUDisappear methods of your view controller.