I have a view that uses a modal view with a page curl to allow for a username to be entered. This username is then verified with a web-based service to see if it is valid.
Everything works great until you enter an invalid username and click outside the modal view. This still checks the username, which is reported invalid and a UIAlertView opens. However, it goes back to the parent view.
Is there any way to get the modal to not dismiss in this case?
I have tried to reload the view but either it isn't working or the UIAlertView is blocking it. The last idea I have is to couple displaying the modal view with the "OK" on the alert for an invalid username. Anyone have any ideas?
If you were not using a UINavigationController You could put something like this in the view controller that calls the modal view:
-(void)dismissModalViewControllerAnimated:(BOOL)animated{
if (_someFlagForBeingProperlyLoggedIn) [super dismissModalViewControllerAnimated:animated];
}
When you tap on the page curl the presenting/parent view controller is sent dismissModalViewControllerAnimated:.
Since you are using a navigation controller your options are limited. This is because UINavigationController is a subclass of UIViewController, and a self centered one at that. When you click the page curl it's dismissModalViewControllerAnimated: is being called.
You still have the option of subclassing UINavigationController and implementing the above method, but that will get messy in a hurry.
Having the UIAlertView "direct back" to the modal login view IS very easy. Have that main view conform to the UIAlertViewDelegate protocol. When you display the alert set that instance as the delegate, and in that class implement the method:
-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
// Enclose in if (buttonIndex == #) for selective calling
UINavigationController* nav = (UINavigationController*)[[UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil] instantiateViewControllerWithIdentifier:#"Preferences"];
[nav setModalTransitionStyle:UIModalTransitionStylePartialCurl];
[self.navigationController presentModalViewController:nav animated:YES];
}
Then when the alert view is dismissed it will show the 'login' view.
You should redisplay your modal view with a little delay, something about 0.3-0.5. that's the amount of time needed to alert to be dismissed and that is exactly animation(the dismissing of the alert view) that prevent the modal view from showing up.
-(void)showModal{
SomeModalViewClass* modalView = [[SomaModalViewClass alloc]init];
[self setModalTransitionStyle:UIModalTransitionStylePartialCurl];
[self presentModalViewController:modalView animated:YES];
[modalView release];
}
-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
//check the button index if needed and then
[self performSelector:#selector(showModal) withObject:nil afterDelay:0.3];
}
Related
I have looked around but haven't found a satisfying answer. My problem is that whenever I call popToRootViewControllerAnimated:(BOOL) it is not doing anything. When I NSLog it, it logs (null).
Let me back up a bit here. I have a table view controller that has a list of things, at the navigation bar up top there is an option to add and that takes me to a new view controller with a segue "Present as PopOver" which gets rid of the principal or main navigation bar. So I made one manually and added 2 bar button items "Cancel" and "Add". When "Cancel" is tapped, it should take the user back to the table view controller and discard changes, when "Add" button is tapped, it should also take user back to the previous table view controller with the changes. But it's not doing anything.
Here is my code.
- (IBAction)cancelButton:(UIBarButtonItem *)sender {
UINavigationController * navigationController = self.navigationController;
NSLog(#"%#", navigationController);
NSLog(#"cancel tapped though");
ListingTableViewController *rootController = [[ListingTableViewController alloc] init];
[navigationController popToRootViewControllerAnimated:NO];
[navigationController pushViewController:rootController animated:YES];
}
As far as the segue, this view controller is not connected to anything, or should I connect it? This is a noobish question indeed. Here is my xcode screenshot.
Check this link for the screenshot of the storyboard
http://i.stack.imgur.com/lqnCF.png
You must call
- (IBAction)cancelButton:(UIBarButtonItem *)sender {
NSLog(#"cancel tapped though");
[self dismissViewControllerAnimated:YES completion:nil];
}
instead of popToRootViewControllerAnimated because your VC presented and not pushed!
When presenting a view, you are not pushing it in your navigation controller, but having it presented. To dismiss it, try using [self.presentingViewController dismissViewControllerAnimated:NO completion:nil].
I am working with Objective C using xcode and SUP 2.1.3 as backend.I am verymuch new to the technology.I have created a project with master detail as the design template.In that in the detail view I am using a popup to display some details.And also I have a button over there. When I click in this button I have to go to the next UIView in popup itself.
For that I have created two more UIViewControllers (viewController1 and viewController2).
And in detailview I have written the code for a popup like,
-(void)popupAgain
{
ViewController1 *viewController = [[ViewController1 alloc] initWithNibName:#"ViewController1" bundle:nil];
viewController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:viewController animated:YES];
[viewController release];
}
And I put a button over their in that popup, I am calling the next popupAgain funcion to get viewController2 like
-(IBAction)next:(id)sender
{
[self popupAgain];
}
-(void)popupAgain
{
ViewController2 *viewController_new = [[ViewController2 alloc] initWithNibName:#"ViewController2" bundle:nil];
viewController_new.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:viewController animated:YES];
[viewController_new release];
}
Now the problem is when I click on the next button I have to dismiss the first popup and display the second.But I am not able to dissmiss the first one even if I am writing the code [self dissmissModalViewControllerAnimated:YES]; in the action for next button like,
-(IBAction)next:(id)sender
{
[self dissmissModalViewControllerAnimated:YES];
[self popupAgain];
}
Please anyone help me to solve this issue.Or do you have any other idea regarding this?I am very much new to the technology.Thank you very much for any help in advance.
See here:
http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ModalViewControllers/ModalViewControllers.html#//apple_ref/doc/uid/TP40007457-CH111-SW1
Dismissing a Presented View Controller
When it comes time to dismiss a presented view controller, the preferred approach is to let the presenting view controller dismiss it. In other words, whenever possible, the same view controller that presented the view controller should also take responsibility for dismissing it. Although there are several techniques for notifying the presenting view controller that its presented view controller should be dismissed, the preferred technique is delegation. For more information, see “Using Delegation to Communicate with Other Controllers.”
This seems to be the patten used throughout Apples applications; Creation of a new record is done through a modal View which needs to be saved or canceled to continue, and editing a record is done through a view pushed onto the navigation stack.
It doesn't seem right to be basically duplicating my ViewController for 'add' and 'edit' but there are several differences in how pushed and modal ViewControllers work which complicate things.
How should I be doing this so it can cover both bases?
-
Differences include.
When pushed onto the stack the navBar appears at the top of the View and can be configured to contain the cancel/save buttons. When presented modally this is not the case so to duplicate the interface a toolbar needs to be created separately and close/save buttons added to this instead.
When dismissing a pushed view we send a message to the navigation controller [self.navigationController popViewControllerAnimated:YES];, when dismissing a modal view we send a message to self [self dismissModalViewControllerAnimated:YES];
You could add the UIToolbar in InterfaceBuilder, and then just hide it in viewDidLoad when self.navigationController is not nil.
As for dismissing, you could have something like:
- (void)didCancel {
[self.navigationController popViewControllerAnimated:YES] || [self dismissModalViewControllerAnimated:YES];
}
This will shortcircuit if your viewcontroller is part of a navigationcontrol, and use dismissModalViewControllerAnimated otherwise.
This should work for your cancel button. For your save button, it is useful to call some sort of delegate method such as:
- (void)didSave {
// do your saving juju here
if([self.delegate respondsToSelector:#selector(viewController:didSave:]) {
[self.delegate viewController:self didSave:whatJustGotSaved];
}
[self.navigationController popViewControllerAnimated:YES]; // noop if currently modal
}
In the delegate's implementation then, you can put:
- (void)viewController:(UIViewController*)viewController didSave:(NSObject*)whatJustGotSaved {
// do stuff with parameters
[self.modalViewController dismissModalViewControllerAnimated:YES]; // noop if not modal
}
I'm adding TabBarItem (Email) dynamically. When I finish with my email, I'm calling 'dismissModalViewControllerAnimated' but it's simply dismissing mail view. How do I unload the view controller?
in my email view controller I'm doing following:
- (void)viewDidLoad => I would like to unload this view controller
{
[super viewDidLoad];
[self showEMail:nil]; => this display and dismisses email (I'm not calling present.. and dismiss... in a row. I'm using delegate methods to present and dismiss, which is fine.)
[self presentModalViewController:picker animated:YES];
[self dismissModalViewControllerAnimated:YES];
}
after selecting my tab bar item, it's loading view controller(Lets say 'ABC View controller') which is presenting my mail modal controller. mail modal controller is being dismissed properly. but I would like to come back to previously selected tab item after unloading the 'ABC view controller'. is it possible? or am i doing something wrong here?
Thanks in advance
Rama
Rama, your question is hard to understand. maybe you need to use delegation for the view controller you are presenting.
In your code, calling [self presentModalViewController...] and [self dismissModalViewController...] in a row doesn't make sense.
You shall call the [self presentModalViewController...] in the first place, make the presenting view controller as the delegate (picker.delegate = self, for instance)
let the modal view controller do its business including exiting (like user hits cancel, close or whatever), then call the delegation method (something like [delegate didFinish...] or [delegate didCancel...]
now it's the presenting view controller's turn to response to the delegation method calling, you can do the modal view controller dismissing here
Note: many UIKit classes practice this pattern, such as UIAlertView, UIActionSheetView, MPMoviePlayerViewController, etc. You shall check them and make your own
I've solved problem by using ViewWiilAppear method to display mail modal presenter.
and i'm selecting the index of tab bar controller after dismissing mail modal presenter.
self.tabBarController.selectedIndex =0;
This solved my problem.
Cheers
I'm implementing a Passcode feature in my iPhone app which has a UITabBarController as a root view controller. I have everything working great in most situations, by displaying a modal Passcode ViewController from the tabBarController when the app goes into the background, like so:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
if ([[NSUserDefaults standardUserDefaults] valueForKey:kPasscodeStringKey]) {
PasscodeEntryVC *passcodeView = [[PasscodeEntryVC alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:passcodeView];
[tabBarController presentModalViewController:nav animated:NO];
}
}
My problem comes when the app is already displaying a modal view controller when it enters the background. Then, no passcode view appears. What would be the correct way to do this? Instead of just sending the message to the tabBarController to present the view, should I be checking first to see what the current view is, then have that present the passcode? If so, how is this done? Thanks.
First - you are leaking memory because you do not release your passcodeView and navigation controller nav.
Second - you could keep a simple BOOL variable that is updated whenever a modal view is presented or dismissed. If there is a modal view, just call dismissModalViewController:animated: in your applicationDidEnterBackground: method.
You could also check the frontmost view controller with [self.navigationController.topViewController class], but I have found this to be unreliable.
What I usually do is to ensure that any views I have that may present a modal view controller to dismiss the modal view controller whenever it is sent the UIApplicationWillResignActiveNotification notification, while over in my app delegate, I set it up exactly like yours.
One caveat though, is that whenever you dismiss the said modal view controllers, you need to ensure that you dismiss them with animated: set to NO before presenting your passcode view controller.