Understanding View Controllers - iphone

I have an TabBar application with 4 tabs. All four tabs have navigation controllers. In the settings tab i have a table with a cell for "Feedback". When the cell is clicked a FeedBackView controller is pushed which contains a feedback form with a few fields. This has a textfield for Category. When the textfield is touched, a modal view controller (FeedBackModalView) is presented with a picker. In the viewDidLoad method of the FeedBackModalView controller I typed NSLog(#"%#", self.parentViewController). In the console it shows the parentViewController as TabBar controller. Why is that? Shouldn't it be showing the FeedBackView controller as the parentView since I'm presenting the modal view in that controller?
I hope i was clear.

Using presentModalViewController with UITabBarController has some issues, and I believe the internal behavior of the method has kept changing in recent SDK versions. The bottom line is, you are supposed to use the root view controller to modally present a view controller. In case you are using tab bar interface, that becomes the UITabBarController object.
In an old version of SDK, when I presented a modal view in a view controller inside a tab bar controller the modal view did not appear in full screen, which wasn't an expected or a documented behavior. Now a modal view seems to appear in full screen anywhere, and I wouldn't be surprised if [self presentModalViewController:animated:] method internally checks self and if it has non-nil parentViewController property, send the message to the parent view controller (which will explain your observation).
My memory is vague and perhaps somebody has to correct me. However, I still believe it's the straightforward thing to understand (and also maybe practice) presentModal... only works with the root view controller.

Related

Calling popToRootViewControllerAnimated from a modal

I have a modal that I am calling presentModalViewController to display from a custom menubar. This menubar is overlaying a viewcontroller that is pushed from a tableView cell.
Now... that all being said, I need to find some way to jump the user back to the root of the tableView from the modal screen. Is this possible? I've been fighting with this for the past couple of hours with no results.
If you're starting from a tablview, drilling down to a detail view via a navigation controller, and then presenting a modal view controller on top of that detail view, you'd have two steps to get back to your list/tableview: First you'd dismiss your modal view controller, then you'd pop your detail view off your navigation stack.
That should put you back where you started (at the tablview), if I'm reading this correctly.
You could pass a reference to the navigation controller to the modal view, and then immediately after calling dismissModalViewControllerAnimated, you can use the reference to the navigationController to pop back to the root view controller.

Is there a delegate in the parent view controller that gets called after a modal view gets dismissed?

After a modal view controller is dismissed, is there any delegate method called to bring the parent view controller to the front?
I ended up using delegation from Apple's View Controller Programming Guide for iOS :
http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ModalViewControllers/ModalViewControllers.html#//apple_ref/doc/uid/TP40007457-CH111-SW14
When it comes time to dismiss a modal view controller, the preferred approach is to let the parent view controller do the dismissing. In other words, the same view controller that presented the modal view controller should also take responsibility for dismissing it whenever possible. Although there are several techniques for notifying a parent view controller that it should dismiss its modally presented child, the preferred technique is delegation.
There was a good example in the CoreDataRecepies sample code when adding a recipe that fit what I was trying to do.
i.e., at the "same time" view[Will|Did]Disappear: is being called on the modal view controller as its view is being dismissed, the view[Will|Did]Appear: are sent to the view controller that is being revealed
the code in here should not really need to differ from the reveal code you used when it was first displayed,
if you need data passed back from the modal controller to the one that displayed it, generally the code that dismisses the modal controller lets the other one know
parentController.item = self.chosenItem;
[parentController dismissModal…

What is the pattern for an Iphone app with both a View Controller and Tab Bar Controller?

I am trying to write an iPhone app that has both a UITabBar controller (and its associated views) and a plain vanilla view controller that is not part of the TabBar (i.e. an initial config page that only gets displayed the first time the app is run).
I am able to put a Tab Bar Controller and a View Controller in MainWindow.xib and shuffle between the two in the app delegate.
While this works I'm wondering if this is the best way to be implementing this.
It doesn't feel very "MVC-ish" to me but I think the two different controllers both need to be root (?)
I don't know how else I would do it.
If the config page is really only a "run once" affair, you could just pop it as a modal view from within the tab bar controller via the presentModalViewController:animated: method. (If on the other hand the config page is ever likely to be required in the future, I'd just add it as another option on the UITabBar.)
You would make the tabbarcontroller the default view. And present the viewcontroller modally in viewWillAppear or similar method. Then when you want to switch to the tabbar, you'd dismiss the modal view controller.

Weird UINavigationController behavior

I am having a bit of trouble with my navigationController in my app. I am using the Kal Calendar component - https://github.com/klazuka/Kal.
I have created the view controller and have go it to appear in the correct position within in my app i.e. Click on a new tab and init the rootviewcontroller as the KalViewController and it sort of loads correctly but the back button is visible on the navBar when it should be the rootView and it is clickable 5 times before going to the true root, it's hard to explain but I have no idea what is wrong.
i have tried it with a table view and clicking on the first element in the tableView takes you to the calendar which works perfectly but this is not what I want/need in the app.
Thanks.
It sounds like you have both a UINavigationController and a UITabBarController. Make sure that the tab bar controller is your “main” view and that there are separate UINavigationControllers for each view controller in the tab bar. The different tabs’ view controllers should not be in the same navigation controller’s view heirarchy.

iPad - topmost modal view controller won't dismiss when there are multiple

I'm working on a dual-iPad/iPhone application.
I'm having a problem that is occurring on the iPad only:
Root view controller is a UISplitViewController on iPad, UITabBarController on iPhone
A modal UIViewController can appear over the root controller
A modal UIViewController can appear over the previous modal controller
On iPad, modal controllers are using UIModalPresentationStyle.PageSheet
Everything works, except dismissing the topmost modal controller from the iPad--the method is called, but the modal view controller doesn't dismiss. I dismiss by calling DismissModalViewControllerAnimated from the previous modal controller.
Any ideas why this wouldn't be working on the iPad?
In all cases, I call PresentModalViewController and DismissModalViewControllerAnimated from the parent controller to work its child modal controller.
I'm using MonoTouch (you can tell by my casing of methods), but that is probably irrelevant. I can take answers in Obj-C as well.
UPDATE, following might make what it should do more clear:
Root => Modal A => Modal B
Dismissing Modal B should just return
to Modal A
Dismissing Modal A should just return
to Root
Are you sure you are dismissing the right view? Inside the modal view, lets say that you want to dismiss the view with a button click. In that button's method, you want to call the DismissModalViewControllerAnimated method. Just say
[self dismissModalViewControllerAnimated:YES];
Present the modal window from the root
when finished, dismiss the view from the modal view's controller.
It's hard to really diagnose the problem without seeing how you are trying to present and dismiss the controller, but that should work. You shouldn't need to do anything from the parent controller once the new view is displayed...
Found a workaround. All of these conditions had to be met to fix it:
First modal has default ModalPresentationStyle
Second modal has UIModalPresentationStyle.PageSheet
My second modal is displayed in the ViewDidAppear of the first. For some reason, I needed to call PresentModalViewController from BeginInvokeOnMainThread. (A one-liner in MonoTouch) This is a trick I learned from Windows development and message pumps. I have seen iPhone devs do similar workarounds with timers--this is much better.
I will post-back if we have trouble getting this through the app store. But for now, it is a good solution for us.