using dismissModalViewControllerAnimated without deallocating modal view controller - iphone

I'm creating an app using the iPhone Utility App framework, and I'm trying to use a navigation controller on the flipside view, as there will be a lot of drilldown options on this view. When I'm done with this view, I call the following code:
- (IBAction)done:(id)sender
{
[self dismissModalViewControllerAnimated:YES];
}
When I dismiss this view, I want to be able to go back to the place in the navigation I was currently at when I reopen this view again. However, when I dismiss this view using this method, the vc gets deallocated, therefore the menu starts back at the beginning when I try to go back to the menu.
Thoughts?

You'll need to retain a reference to the object (I'm calling it the options controller). I would say the easiest way is to create an iVar in the presenting view controller that references the options controller. Then, when you go to present the options controller again, just present the referenced options controller rather than creating a new controller. If different view controller objects can present the options controller, you'll need to either pass that reference around, or store it in some object that all the other view controllers have access to.

Hmm not much code so maybe I'm misunderstanding your setup, but...
You could use the AppDelegate to store (as a property) your current position (index) in the views collection of the Navigation controller, and then write a method that pushes to that (stored) position when you re-visit it later.
Might be an easier way to do it though..

So what you want is to flip from a view to another view? If you want to keep the navigation bar status between flipping, I recommend you use only one view controller to control this 2 views. you can use + transitionFromView:toView:duration:options:completion: of UIView to flip views.

Related

How does iOS know which view controller should be active?

If I want to replace one screen of an app with another, but I don't use a navbar/tabbar controller, then I could just remove oldViewController.view from window and add newViewController.view to it. That's all, now newViewController will get rotation events, etc.
But UIView does not reference "its" controller, so how is this possible, how iOS know it should make newViewController an active one? Does iOS do some magic, it internally references controller from view or what?
UPDATE:
I think I was misunderstood: I don't ask how to make some view controller an active one - I know that. I'm just curious, how is it possible that I pass some view to UIWindow object ([window addSubview:view]) and it somehow finds view controller although view doesn't know its controller.
yeh I had the same question like you. and I figured it out.
UIView is derived from UIResponder. and UIView must subclass UIResponder::nextResponder.
Its default implementation is returning a view controller of the view (if it hadn't, it would be super view)
So, consequently view can see its controller. that means window know the topmost view and also
its controller.
good luck.
Unfortunately, iOS only send events to the first ViewController of the stack. You can try and present a new one on the top of others with video for example, it will never rotate.
If you don't use navbar/tabbar controller you will have to add and remove everytime from the Window to keep only one at the time if you wand to have events.
The main UIWindow class for your application will have a view controller set in its rootViewController property. That controller's view is the "main" view for the app. This is usually setup in the main .xib for the project. That view controller will receive the usual events like "viewDidAppear" or "willRotateToInterfaceOrientation". You can put up your own view over top of it if you want to, but you will need to manage those events yourself. Usually you don't do that though. You just use a UINavigationController or UITabBarController as your rootViewController and allow them to manage getting the events to new "pushed" view controllers, or you popup view controllers with "presentModalViewController".

How to pop to an arbitrary view controller from anywhere in a navigation stack

I'm working on a navigation based app, and I chose it so that I can push and pop controllers on and off the stack. It's easy enough to move forward - just push a new controller. And moving back is easy as long as you go to the root view controller. There is a method called popToViewController:animated, but I didn't create the controller I want to pop to from within my current view controller, so the compiler complains that I haven't declared it. I know it's the second controller on the stack (one above the root). Can I use that to get there?
The viewControllers property of a UINavigationController has the viewControllers in order that they were pushed, so you can use that and your knowledge of which view controller it is to pop to that view controller..here is a reference UINavigationController ref
I generally create a NavigationController object which has knowledge about both my UINavigationController and my viewControllers. If you give each of your VCs a reference to an object like this, or make it a singleton, then it can handle things like this for you.
There is nothing wrong with embedding navigation logic in view controllers, but it can make them harder to maintain when they know about every other view controller. Encapsulating navigation logic in a shared object makes your app easier to understand and maintain.
YMMV

How to tell if view has appeared via popping or not?

Using a UINavigationViewController, how do I find out how a view has appeared?
The view has either appeared in a straightforward manner, as the first view in the UINavigationController stack. Or it has appeared because a second view has been popped and the first view has revealed itself again. How do you find out which of these happened?
The only reliable way to do this, as far as I'm aware, is to subclass UINavigationController and override the UINavigationBarDelegate methods:
– navigationBar:shouldPushItem:
– navigationBar:didPushItem:
– navigationBar:shouldPopItem:
– navigationBar:didPopItem:
Don't forget to call super, of course.
Simple approach is to add a property to your RootViewController to track whether or not it has pushed another view onto the navigationController.
-(BOOL)hasPushedSecondView;
Initialize to NO in your init method.
Before pushing secondViewControllers view onto the stack, update the property to YES.
In viewWillAppear, check the value and update your view accordingly. Depending on how you want the application to behave you may need to reset the hasPushedsecondview property back to NO.
you could take a look at the leftBarButtonItem or backBarButtonItem, based on how your application is written and determine how the view appeared. If it is on top, unless you have a custom leftBarButtonItem, there would be no object there.
You can determine this directly via a couple of methods on your UIViewController subclass.
From Apple's documentation:
Occasionally, it can be useful to know why a view is appearing or
disappearing. For example, you might want to know whether a view
appeared because it was just added to a container or whether it
appeared because some other content that obscured it was removed. This
particular example often appears when using navigation controllers;
your content controller’s view may appear because the view controller
was just pushed onto the navigation stack or it might appear because
controllers previously above it were popped from the stack.
The UIViewController class provides methods your view controller can
call to determine why the appearance change occurred.
isMovingFromParentViewController: view was hidden because view controller was removed from container
isMovingToParentViewController: view is shown because it's being added to a container
isBeingPresented: view is being shown because it was presented by another view controller
isBeingDismissed: view is being hidden because it was just dimissed

Managed Object Context in Tab Bar View

Ok. this one's a challenge.
I have a tableview within a navigation controller.
I push it from the root, where I have an add action that allows me to add a new record. That works fine.
Now what I've tried to do is add this tableview to a tab bar view (without a tab bar controller cuz that won't work) but within the same navigation controller.
So what I want to do is this: Root > TabBarView (loads Tableview) > add new record.
The problem lies in the managed object context, I get the whole "can't find entity error" but I have no idea how to fix it.
I've managed to get the AddRecord modal view controller to show up from the tabBarView, but it presents itself without a navigationbar, whereas if I try to add a record in the solitary tableView (outside of the tabbar) its no problem.
I'm now calling my methods from the TabBarView's navigationBarbuttons, routing through to the tableviews methods.
I know my methods have to be called from the tabBarView instead of the actual tableview now, and they do fire, but I don't know how to manage the MOC when its in a tabView.
Oh, and this is based on coredata recipes and books, so when the add record method is fired, it creates a new MOC to create it, then reintegrates back in the main MOC when you're done.
Any ideas?
It sounds like you have a couple of problems.
"Can't find entity" error -- this depends on which Managed Object Context you're using. If you created a separate MOC to manage the object you're editing (which is a good idea, by the way), make sure you assign it a Persistent Store Coordinator. This is how an MOC discovers what objects are available. If you're using the MOC created in the App Delegate, make sure you're spelling the name of the entity correctly.
No Navigation Bar in sheet -- When you push a view controller onto a navigation controller, its navigationItem is used to populate the navigation bar. When you present a view controller as a sheet, only the view controller is displayed. It is not embedded in a navigation controller. In order to get the navigation item to display, you'll need to create a new navigation controller with your view controller as the root, and then present the navigation controller's view.
As far as the main MOC goes, views and controllers should be irrelevant. Obtain a reference to the MOC in whatever controller you are using and operate with that MOC. If your application delegate creates the main MOC, make it a property of that delegate and access that from your view or tab controller.
I don't quite follow what navigation problem you're having, but if there's no navigation bar when you need one, I suspect you need to create and add a UINavigationController somewhere that you're adding a UIViewController subclass. Make the subclass the root of the new UINavigationController and put the controller into the tab or whatever.
Your managed object context (MOC) should not be dependent on navigation or views. It's part of the model. (Although as you know, a 2nd MOC for a cancelable edit view would be dependent on navigation to the extent that you create it for use by the editor.)

iPhone dev view swapping

So I'm trying to find out the best way to swap views for an iPhone game I'm making. I have a "root view controller" that has a reference to all the view controllers I want to swap between. So I add the main menu view to this root view controller - [self.view addSubview:mainMenuController.view]; - Then in the main menu view I have an instructions button. I define an IBAction in the mainMenuController to respond to the instructions button being clicked. From there, I call [self.view removeFromSuperview] which works great. It gets rid of the main menu. So next I want to add the instructions view. I figured that it would be as simple as [super.view addSubview:super.instructionsController.view], but no luck! I've thought of a few ways to get around this, but they all seem very inelegant, as I would like to keep all references to my view controllers in one place, the root view controller. Any thoughts?
Could you not have your main menu view controller tell the root view controller that it's closed, along with a reference to what view it should load next? I'm assuming you're not doing something akin to what UITableView does, in which case you'd likely want to use a stack.
Are you mixing super (an Objective-C keyword) with self.superview (an UIView property)?
At any rate it's indeed a better design to inform your main controller to switch to another view, rather than making that decision from the added subview.
I just got around it by setting a delegate property in each of my controllers to the root view controller.