UINavigationController and switching next-prev item within one level - iphone

could anyone help me with the next question. I am working on an app with the navigation similar to Notes app has. The problem I faced i how to implement navigation within one level and keep root view as the previous screen. So the scenario I need to achieve:
1. Drill down from the top level list to the detailed view.
2. From this detailed view navigate to the detailed view of the next/previous item.
3. Back button should lead to the root view.
I've tried several approaches and no-one worked fine for me. The most right solution from my point of view is to create a middle controller between the root and detailed controllers to handle this next/prev redirects. But the main problem here is that switching from one detailed view to another the navigation pane stays the same, so it's not involved in the animation, whether Notes app work right in this case.
Could you point me how it' better to arrange controllers interaction in this case?
Thanks in advance. Sorry for quite big post, was trying to be as informative as possible.
Best regards,
Roman

I think the best implementation is this way:
Say you have a Note class where the data is stored.
You could have two view controllers, one with the list of notes and one with the details.
Both of these can be added to a navigation controller.
Then, when you want to switch to the next note, you retrieve that object somehow and assign it to your detail controller with a -setNote: call. That method will be responsible for changing what the outlets are displaying.

I've resolved this question - it's enough to pop current view and push new one, created for the next object in the list. The only think to remember is to save the reference to the navigation controller before the pop call, because after it self.navigationController becomes nil.

Yeah, it's misbehaving badly. Jongsma's reply is the best. In case you wanted to re-create controllers, I've found this to work:
[parent performSelectorOnMainThread:#selector(showMyItem:)
withObject:myNextItem
waitUntilDone:NO];
[self.navigationController popViewControllerAnimated:NO];
performSelectorOnMainThread delays execution of the method until the next run of the main loop, and by then the previous controller is removed already and navigation controller is in a stable state.

Related

Making a segue within a navigation controller without pushing

I'm making an app where you at one part should be able to switch back and forth between three pages and pick files from each one of them. These will be added to an array as you pick them.
Problem is that the only way I know to link between these pages would be to use a tab bar, which doesn't work within a navigation controller...
Do you have any idea of what might work?
Thanks in advance
What about a UIScrollView`?
Make your three pages as separate UIView's in your xib. Then, add them side by side into your scroll view in viewDidLoad.
If you set paging = YES on your scroll view then that should work.
I don't know if I understood you well, but what do you think about using a UISplitViewController?
Using its MasterViewController as a place with buttons to switch between the three pages and in the DetailViewController the corresponding View of each one.
It might not be the exact answer to the question, but can very well be a solution to other people finding this thread...
After a while of experimenting, I found out that I could just change the content in the UITableView for each button push instead of having three separate UITableView's.

Navigation Controller design for multiple duplicate views

I'm having a hard time understanding what approach I should take. I have a TableView controller with a list of questions, if you click a row it pushes a new QuestionViewVontroller that displays the question, answers, and next button (or done button). When a user clicks next I want to load the next question (from the tableview list) but I still want the navigation to work (back button will take you to TableView).
I'm starting to think I should keep the same QuestionViewController and just load in the question data. Is this right? Or should I use a modal view?
You have a couple of options here.
Use the same QuestionViewController and just repopulate it, like you mentioned.
Push a new QuestionViewController and use custom back button that either pops to the root view controller or pops to a given view controller.
The code for both options in #2 is below, where "self" is the current view controller (your question controller).
[self.navigationController popToRootViewControllerAnimated:YES]; //this would pop to your UITableViewController, assuming it was the root
[self.navigationController popToViewController:yourTableViewControllerHere Animated:YES]; //this would work as long as you passed a reference to your UITableViewController to your question controllers
It's up to you how you choose to solve your issue. However, if you decide to use the same QuestionViewController, include a catchy animation when importing the new question so the user knows what is happening and to make your app that much cooler :)

How do I switch ViewController instead of adding to stack?

I have a number of objects linking to each other in a circle. Each object holds a reference to it's neighbors, square and triangle are different class types:
The tow classes, triangle and square, are made visible with a ViewController, and they link to each other with segues.
So far, no problem. However, while I'm browsing around in my structure, I keep adding ViewControllers on top of each other. Not only does this seem a bad practice memory-wise, but it also presents the problem that when I want to quit this structure, I have to back-track by closing all ViewControllers that I opened.
So what I'm looking for, is a way to not add the next ViewController on top of the current on in the stack, but to replace the current ViewController with the next one.
I've been looking for a while for a solution, but have little success. So I feel that doing what I want is either impossible, or I'm just not getting an obvious point and don't know what to look for. Do I need a RootViewController for something like this? Or should I create a custom segue that dismisses the old ViewController before adding the new one? I'm really at a loss here.
Add all subView once , in viewDidLoad and give tags to all you SubView after that where you you want to show that view in viewController don't add it just bring it to front by calling the function [[self.view viewWithTag:1]bringToFront]
Since you are probably using a navigationcontroller, you should have a look at the UINavigationController reference. There are methods to modify the navigation stack. You cannot do this only with a storyboard. You will need some custom code.
You should have a look at the UINavigationController method setViewControllers:animated:.
Sounds like you want to do one of a couple things
Replace your rootViewController
Have a rootViewController which acts as a container for a single UIViewController and change that out as needed. In iOS 5 you can do this with a custom UIViewController, but or you could use one which Apple provided.UINavigationController` can do it, but unless you are also using it to navigate a tree like structure of view controllers it's probably not the best option.
Your best answer sort of relies on your need.
If your controllers don't have much state or don't get swapped in and out a lot you could use option 1.
If you expect users to swap between controllers often and quickly and/or your controllers require significant setup or have a lot of state then you might want to a NSArray and just use presentViewController:animated:completion: to show different controllers when needed. Storing your controllers in a NSArray has the added bonus of easily being able to identify their neighbors.
The UINavigation controler's method setViewControllers is an option.
Another would be to pop the most rencent view controller using popViewControllerAnimated:
In some cases popToRootViewControllerAnimated: would be best or even popToViewController:animated:. Hoever, I personally was not successful using popToViewController:animated: but that may have been my fault at that time.
Yes, I think you need a root view controller. I myself tried to exchange the root view controller the other day but failed doing so. In the end it was probably not the most elegant solution but easier for me to implement some dummy root view controller which does nothting but display my app logo in the background (Same as the default image but moved into negative coordinates in order to match the default image on startup. It is laying 'behind' the navigation bar and status bar.). It could show some empty black background or so. In the end it is will most probably never be visible.

When to reuse navigation controllers?

I'm trying to develop an app having a tab bar controller with 5 bar items.
All of the items need navigation controllers.
I just wanted to know whether it is possible to reuse the same navigation controller for all the items.
Are there any restrictions or things I need to keep in mind to do this?
Every tab in a UITabBarController should have its own UINavigationController, if you're in need of one that is. You push and pop UIViewControllers onto/off a stack and every UINavigationController has its own stack. Since the UIViewControllers from your other tabs have nothing to do with the navigation flow from the current tab, each tab should have its own UINavigationController.
I think I may have misinterpreted your question originally here... Navigation Controllers actually fine to re-use I think... I'd recommend release and creating a new on when the tab is changed if that makes sense within the application. You could give a reference to it in your appDelegate so it's easily accessible from each view controller.
Original reply follows in case I'm misinterpreting it still :S
The separation is entirely up to you, but for code clarity it's nice to have each viewcontroller separate. As a lot of the code will be found in your controller it's quite nice to separate out as much as possible. You can use the same controller, but change it's view property when each item is clicked, but it doesn't really save much and wil make for harder to maintain code...

How to tell when a view has become active

I'm using a navigationController to push a new view onto the stack. Once I'm done with that view I pop it. I want the original or root view at the bottom of the stack which then becomes active to know when this has happened to it can call a method on itself
There are two options
1. implement -(void) viewWillAppear:animated: This is often a useful strategy for knowing that a view is about to become visible. If you are always doing the same thing when this happens, then this is quick and easy.
2. Send a NSNotification. This is useful when you want your underlying view to perform some action in response to a particular event happening elsewhere.
Use the viewWillAppear delegate. It is called right before showing the view.