Modal View Issue - iphone

I have an issue with some of my views, here is a breif outline of my setup:
Tab Bar Controller
|
--View Controller 1
|
--View Controller 2
|
--View Controller 2
On a certain action, View Controller 1 will display a modal dialogue. Within this dialogue, if the user performs another action, then another modal dialogue is shown, using the first modal dialogue to present the view.
On the 2nd ModalDialog I have a UITextField, however when I attempt to type into the text field, nothing happens. Even though the keyboard is displayed and the textFieldDidBeginEditing method is called. I have setup the UITextFieldDelegate and the nessessary responders, but to no avail.
Does anyone know what would cause this issue?
Many Thanks

I've found that on a number of occasions with changing views and with popovers that text fields haven't focused correctly with symptoms like you describe. On these occasions I end up deferring the becomeFirstResponder call until the animation has finished or the view has loaded - for example in a view controllers viewDidAppear method.
Or, simply delay the call to becomeFirstResponder with an appropriate guestimate of the time it will take for the views to change / animate / etc. ie:
[textField performSelector:#selector(becomeFirstResponder)
withObject:nil
afterDelay:0.3];

I would try to 'chain' the modal dialogs from the view controller if that's possible.
The VC opens the 1st modal dialog
Your 1st modal dialog notifies the VC (using delegation probably).
(Maybe required) Close the 1st modal dialog
The VC opens the 2nd modal dialog
Happiness!

I'm not sure what you mean with "modal dialogue" -- I assume you mean either a modally presented view controller with a UIModalPresentationFormSheet modal presentation style or a UIPopoverController.
Here's my best guess: I'm pretty sure that your "modal dialogue" captures all user interactions (by default). So when pushing the first one, it captures all input focus. When pushing the second one, it's capture conflicts with the previous one and hence the keyboard will not work.
Anyways, both types of "modal dialogues" are not meant to be stacked. Even if it may work technically, I dislike like it form a interaction-design perspective. Instead of trying to fix the bug or work around it, try to rethink you modal dialogue. You may fit everything into a single one. For example by using a navigation controller inside that view, or by replacing the the view or by flipping it's contents... etc.
Hope this helps, Max

If I were you I would consider revising the navigational hierarchy. Modal dialogs are considered bad enough as it is, but incorporating a modal dialog within a modal dialog is user interface suicide. It causes confusion to the user and is very non-traditional. Is there any way you can use the first modal popup and simply exchange the content?
A side note: You mentioned setting up the view as being a UITextViewDelegate. Did you the view as the delegate for the textbox? Are you returning NO or FALSE from - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string?

Related

How can I load into a different view in a popover?

I have some code that opens a popover window that displays some text. This is done by an action segue rather than actual code in a storyboard. Is there any way, that I can load into a different view by pressing a button on the popover view and have it load into the next view? I've tried using another action segue, but it puts a popover into my current popover over the button that I press. Thanks!
This kind of thing can't be done with just storyboards; some code will be necessary.
Here's how I would do this: instead of trying to use two separate popovers, use one popover with kind of a "nested" setup. The popover's content view controller would contain, say, a Page1ViewController and a Page2ViewController. When first displayed, the main controller would install page 1's view. You could maybe wire the action from page 1's button directly to the main controller, but I recommend that you use delegation for this. Create a protocol that's something like Page1ViewControllerDelegate and adopt the protocol in your main controller, then in the delegate method for page1ControllerRequestTransition(_:) or whatever you choose, just grab the page 1 view out and swap the page 2 view in. You can even have the two views be different sizes; the popover will automatically adjust itself.
Oh, and don't forget to disable translatesAutoresizingMaskIntoConstraints and add appropriate constraints to fix the four sides of each page's view.

iPhone Storyboard, programmatically calling segues, navigation issues

So I have an iPhone app. It has a simple structure, all based on a UINavigationController.
I have a storyboard that has one view, a segue to another view, etc. Now this other view has a UITextView that I do not want to edit on this screen - if the user taps this, I want it instead to fly over to a second screen which basically has the same text view, but this one is full-screen, and the user will edit the text on that screen before returning to the previous screen.
So I capture the textViewShouldBeginEditing method. I previously, in the storyboard editor, manually created a push segue from the previous view controller to this new view controller, and named it so that I can call it by it's identity, which I do with:
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
// This is called when the user clicks into the textView as if to edit it.
// Instead of editing it, go to this other view here:
[self performSegueWithIdentifier:#"editMemoSegue" sender:self];
// Return NO, as I don't actually want to edit the text on this screen:
return NO;
}
Seems reasonable. And it works. Sorta. It does in fact shoot me over to that other view. That other view's events fire up, I set it's text view to become first responder, I edit the text on that screen. Everyone's happy.
Until I want to use the back button to return to the previous view.
Then I quickly find out - my navigation stack is foobared. Most of the time, I have, for some reason, TWO instances of my new editing controller on the stack, so the first time I hit the back button I get the same stuff over again. Then, oddly, occasionally, it will work as intended, and I will see my previous controller with only one back click.
I started reading the log, and I found this:
2012-12-09 09:41:03.463 APP[8368:c07] nested push animation can result in corrupted navigation bar
2012-12-09 09:41:03.818 APP[8368:c07] Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
2012-12-09 09:41:03.819 APP[8368:c07] Unbalanced calls to begin/end appearance transitions for <SecondController: 0x83881d0>.
So obviously, I'm doing something incorrectly here. The question is, what? And how do I do what I want in the way that correctly appeases the tiki gods of the iPhone framework?
Check to see if the textViewShouldBeginEditing is being called twice. I've noticed that these kinds of delegate calls sometimes are.
How is your #"editMemoSegue" being created on the storyboard? is it created from the textView? if it is then you should recreate it directly from the view controller or from the top status bar on the view controller that way it wont be called twice when you touch the trigger object and when you call it programmatically.

What to do about "Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted."

I'm writing an iPhone app using Appcelerator Titanium Mobile. I am hiding and showing the tab group based on what window has focus.
dashWin.addEventListener("focus",function(e) {
if (dashWin.tabGroupVisible == true) {
dashWin.tabGroupVisible=false;
tabGroup.animate({bottom:-50,duration:500});
}
});
The code above hides the tab group when dashWin receives a focus event. However, I see this message in the Titanium console when the event fires while running in the iPhone simulator:
Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
A Google search turns up one result: Another StackOverflow question that may have a hint as to what's going on.
I got this error when I linked Action Segue or Selection Segue from one view to another view through storyboard and performed the same segue programmatically again, which makes the navigation controller perform the same segue twice.
2 solutions for this case:
Removing the code that pushes the view. Just let storyboard perform the segue for you. This is good for most situations.
Replacing Action Segue or Selection Segue with Manual Section and do - (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender by yourself. You may find this solution useful when you want to customize the behavior of segue according to the sender.
Usually a tab group acts as the root of your app's navigation. When a user taps a tab, that tab's window is focused.
Next, when a user triggers an action that requires a new window appear, it usually appears either modally or on top (in the navigation stack sense) of the current window. In the latter case, tell the current tab to open the new window.
If you set the tabBarHidden property to false (when you create the new window), the tab bar will be hidden for you when the new window is opened by the current tab.
Will this more standard approach work for you?
I had segues that were leading back to my main navigation controller which was causing this. I fixed the problem by setting the main navigation controller back to the top of the stack. Here is the code:
- (void) viewDidAppear:(BOOL)animated
{
[self.navigationController popToRootViewControllerAnimated:NO];
}
Recently, I've faced the same problem. The reason was:
-I was trying to pop view controller twice by mistake.
you can check this crash by setting breakpoints on push and pop View controllers

viewWillAppear not getting called for detailView of UISplitViewController

I am experimenting with the splitViewController, introduced for iPads and am stuck at a point. I have a button on my detail view of the splitViewController, clicking on which a modal view opens. Now I want to change the positoning of UI controls on the detail view when the modal view gets dissmissed.
A pretty obvious way of doing this would be to catch the view transition in the ViewWillAppear method of the detailView. But it's not being called in this case. I remember facing the same problem in tabBarController where [tabBarController viewWillAppear:animated] was needed to be set before viewWillAppear of views in each tab item got called. I tried doing this with the splitViewController as well, but this doesn't seem to to work.
Any Ideas??
If the positioning is required due to an action that occurred in the modal view, you should use an explicit delegate callback. That will allow you to clearly specify the control flow and resulting behaviour of your app.
You should then define a protocol that has specific methods that carry pertinent information about the action taken. When the action occurs in the modal, perform the protocol method on the delegate, and it can react to that event (for you it seems to be a re-layout of button positioning).
To get an idea of the methods that are abstract enough to handle generic modal behaviour, look at UIAlertViewDelegate protocol. Here the delegate will get an alertViewCancel: message when the user decides to take no action, or alertView:didDismissWithButtonIndex: when they selected one of the options presented to them.
That is a good start for how to define the protocol.
If you need a many view controllers to react to the action taken in the modal, say a Sign In modal, then a better mechanism is notifications.

Why is a UITabBar considered Modal?

Reading the Apple documentation on the UITabBar states,
The most common use of a tab bar is to
implement a modal interface where
tapping an item changes the selection.
With my definition of Modal being:
A modal view is one that has to be
dismissed before you can do anything
else.
But that's not always the use case. I could be interacting with the content view of the UITabBar's first item/button, and that could allow me to reach another view.
OR, I could select another item/button from the UITabBar and reach yet another view.
So how is that considered Modal? (Or is my use case not Modal, and they are just saying, in general, its used Modally?)
I think "modal" here means different "modes".