I'm having a similar issue to Anthony Chan's question, and after trying every suggested solution, I'm still stuck.
Somehow, only after interacting with my UIAlertView, I'm unable to dismiss the keyboard in another view of my app. It's as though the Alert is breaking my UITextField's ability to resignFirstResponder. Below I instantiate my UIAlertView, which then calls its didDismissWIthButtonIndex method. Then, I call the showInfo method, which loads another UIViewController.
UIAlertView *emailFailAlert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"error message text."
delegate:self
cancelButtonTitle:#"Not now"
otherButtonTitles:#"Settings", nil];
[emailFailAlert setTag:2];
[emailFailAlert show];
[emailFailAlert release];
Once the 'Settings' option is pressed, I'm calling this method:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
if ([alertView tag] == 2) {
if (buttonIndex == 1){
[self showInfo:nil];
}
}
}
My showInfo method loads the other ViewController, via the code below:
- (IBAction)showInfo:(id)sender {
FlipsideViewController *fscontroller = [[FlipsideViewController alloc] initWithNibName:#"FlipsideView" bundle:nil];
fscontroller.delegate = self;
fscontroller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:fscontroller animated:YES];
[fscontroller release];
}
Upon clicking any textField in this Flipside VC, I'm unable to dismiss the keyboard as I normally can with - (BOOL)textFieldShouldReturn:(UITextField *)textField, and [textField resignFirstResponder]. I've omitted this code bc this question is getting long, but I'm happy to post if necessary.
The interesting part is that if I comment out the [self showInfo:nil] call made when the button is clicked and call it by clicking a test button (outside the alertView didDismissWithButtonIndex: method), everything works fine. Any idea what's happening here?
Thanks in advance!
When an alert, with more than one dismissal option, is called above a keyboard - the keyboard becomes un-dismissible with resignFirstResponder on the active textfield;
You will need to dismiss the keyboard before showing the alert.
Assuming your UITextField is called myTextField;
[myTextField resignFirstResponder]; //That's the only line I added
UIAlertView *emailFailAlert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"error message text."
delegate:self
cancelButtonTitle:#"Not now"
otherButtonTitles:#"Settings", nil];
[emailFailAlert setTag:2];
[emailFailAlert show];
[emailFailAlert release];
I hope this helps anyone who had to deal with this oddly obscure issue.
You should not call alertView:didDismissWithButtonIndex: directly. This delegate method will be executed automatically in all cases after the alert has disappeared. Otherwise the code will be run twice!
Related
When popping a view I want to save some data, by asking confirmation. I'm asking confirmation using UIActionSheet. But irrespective of my response in action sheet, the view is changing in background, it creates some problem for me to use the response. I'm using navigation controller to switch views. How can I solve this
TIA
Better option is to use uialertview for asking confirmation.To do this follow this step:
Insure your header file contains the following:
#interface YourViewController : UIViewController <UIAlertViewDelegate>
Now when asked confirmation add this code:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Message" message:#"Are You Sure" delegate:self cancelButtonTitle:#"YES" otherButtonTitles:#"NO", nil];
[alert show];
[alert release];
Now after pressing one button below delegate will be called so add in .m file of app
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
// the user clicked one of the YES/NO buttons
if (buttonIndex == 0)
{
NSLog(#"NO button pressed");
}
else
{
//Save data here
NSLog(#"YES button pressed");
}
}
#PooLas If I understood you correctly, You use uiactionsheet for user confirmation, while in background (actually under actionsheet) you change view controllers. Well, you can't do that, because delegate must be attached to controller which shows it up (if i am wrong, correct me). So when you click button, you can only first dismiss actionsheet and then change view controller, but not opposite – PooLaS
In my iPhone app, I have a NSObjectA class and a UIViewController B class. I want to call a instance method in B class from A. I used the following code.
Bclass *vc = [[Bclass alloc]init];
[vc hideAlert:NSString];
[vc release];
and in B class:
- (void)hideAlert:(NSString*)message{
UIAlertView *shareAlrt = [[UIAlertView alloc] initWithTitle:#""
message:message
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[shareAlrt show];
[shareAlrt release];
}
and the method called and show a AlertView. When click on the Ok button, I want to navigate to class Cclass.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
Cclass *vc = [[Cclass alloc]initWithNibName:#"Cclass" bundle:[NSBundle mainBundle]];
[self presentModalViewController:vc animated:NO];
[vc release];
}
}
But when I click on the Ok button, the app crashes. Whats happening here? I have added <UIAlertViewDelegate> in the B class.h file, but still the same error. Please help
I am getting the error code *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType alertView:clickedButtonAtIndex:]: unrecognized selector sent to instance 0x81baa80'
Just change the method
- (void)hideAlert:(NSString*)message{
UIAlertView *shareAlrt = [[UIAlertView alloc] initWithTitle:#""
message:message
delegate:self
cancelButtonTitle:nil
otherButtonTitles:#"Ok",nil];
[shareAlrt show];
[shareAlrt release];
}
This has been answered by presuming that u have no other button except cancel button titled as "OK". Assumption is made by seeing your displayed code.
You have used Cancel button on which u cant handle delegate to perform any action.
If you look at the documentation of UIAlertViewDelegate class reference
Optionally, you can implement the alertViewCancel: method to take the
appropriate action when the system cancels your alert view. If the
delegate does not implement this method, the default behavior is to
simulate the user clicking the cancel button and closing the view.
would you please look at that piece of code:
/* This app is a game, the user can click an "abort" button anytime,
* and he/she is therefore asked for confirmation ("really abort game?")
*/
- (IBAction)btnAbortClicked:(id)sender {
UIAlertView *alert = [[UIAlertView alloc] init];
[alert setMessage:#"Really abort game?"];
[alert setDelegate:self];
[alert addButtonWithTitle:#"Yes"];
[alert addButtonWithTitle:#"No"];
[alert show];
[alert release];
}
/* Delegate method (I don't like it, I wish I had modal blocking windows) */
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0)
[self quitGame];
}
/* pop the view controller */
- (void)quitGame {
[self.navigationController popToRootViewControllerAnimated:YES];
}
The problem is simple - but apparently not enough for me to solve. The UIViewController gets popped, but doesn't get deallocated. And the problem is strictly related to the UIAlertView, because if I just call quitGame from btnAbortClicked:, the view controller is popped and immediately deallocated.
Instead, it seems some mysterious entity retains it.
Can you help me? Thanks in advance.
Well, I think that you're still inside the alertView when clickedButtonAtIndex is called. I'd suggest moving to alertView:disDismissWithButtonIndex instead, so that you're called after the alertview disappears.
I have a Customized UIAlertView.I have a UITextField in that AlertView, which becomes the firstResponder as soon as it is shown. Now I need to dismiss the keyboard for that UITextField when user touches somewhere else in the AlertView. I have touchesBegan event for that.
Everything is in place and works fine, except when I call resignFirstResponder on the UITextField, it resigns from being the first responder but the keyboard is not dismissed. Is there any way to dismiss that keyboard.
I was looking for the solutions and found a similar post here with no answers
If anyone was able to find a way out please let me know. I even tried the following way, but its not working
UIWindow* tempWindow;
// Because we cant get access to the UIKeyboard throught the SDK we will just use UIView.
// UIKeyboard is a subclass of UIView anyways
UIView* keyboard;
// Check each window in our application
for(int c = 0; c < [[[UIApplication sharedApplication] windows] count]; c ++)
{
// Get a reference of the current window
tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:c];
for(int i = 0; i < [tempWindow.subviews count]; i++)
{
// Get a reference to the current view
keyboard = [tempWindow.subviews objectAtIndex:i];
// Loop through all views in the current window
if([[keyboard description] hasPrefix:#"<UIKeyboard"] == YES){
[keyboard removeFromSuperview];
}
}
}
You must call resignFirstResponder on the UIAlertField,
eg:
[textField resignFirstResponder];[alertView resignFirstResponder];
Are you using custom code to show the keyboard? If not, try using the code from this StackOverflow question. I suspect that the resignFirstResponder message is not getting to the right control.
(The code in that answer is generally useful and sorely lacking from the SDK, IMHO.)
[self resignFirstResponder];
self means UIAlertView.
In my case it works.
There's no need to send a resignFirstResponder to the UIAlertView subclass. Just override becomeFirstResponder to return NO in UIAlertView subclass.
Apparently when you resign first responder on the UITextField, the UIAlertView becomes the next responder, keeping the Keyboard in place for some obscure reason.
Resigning that one too makes the keyboard disappear or better indeed override the becomeFirstResponder to return NO.
In my case this solution makes the UIAlertview animate to the upper left corner and animates back in place immediately after which looks very ugly and I cannot seem to find out why this is, but maybe someone else has some thoughts on that?
Here is my code extract in a class derived from UIAlertView:
- (BOOL)becomeFirstResponder
{
return NO;
}
- (void)someCustomButtonClicked:(id)sender
{
[textField resignFirstResponder];
// ...
}
-[UIView endEditing:]
http://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/UIView/UIView.html#//apple_ref/occ/instm/UIView/endEditing:
(Extra text because Stack Overflow requires at least 20 characters.)
Try these methods
-(void)viewDidLoad
{
[super viewDidLoad];
UIAlertView *loginAlert = [[UIAlertView alloc] initWithTitle:#"Welcome" message:#"Please Enter Login and Password" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[loginAlert setAlertViewStyle:UIAlertViewStyleLoginAndPasswordInput];
[loginAlert textFieldAtIndex:0].delegate = self;
[loginAlert textFieldAtIndex:1].delegate = self;
[loginAlert setTag:777];
[loginAlert show];
[loginAlert release];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
And you should add the UITextFieldDelegate in the header file.
I met the problem just now.
Here's how I've solved the problem:
First, make your textField.delegate = self;
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Title" message:nil delegate:self cancelButtonTitle:#"cancel" otherButtonTitles:#"OK", nil, nil];
UITextField *oldPassWord = [alertView textFieldAtIndex:0];
oldPassWord.delegate =self;
UITextField *newPassWord = [alertView textFieldAtIndex:1];
newPassWord.delegate =self;
[alertView show];
Then, [textField resignFirstResponder];
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
[[alertView textFieldAtIndex:buttonIndex]resignFirstResponder];
}
My alertview appears twice and requires 2 user clicks to dismiss.
- (void) showAlert: (NSString *) message
{
UIAlertView *av = [[UIAlertView alloc] initWithTitle:#"You chose"
message: message
delegate: self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"ok",nil];
av.tag = SLIDER_ALERT;
[av show];
}
I am then releasing the alertview in the delegate method "alertView: (UIAlertView *) alertView clickedButtonAtIndex: (int) index"
I suspect the problem is that I have built my own view hierarchy programmaticaly. I have one parent view for the viewcontroller. Under that i have 2 other views (parentView -> subview1 and subview2). I've tried to call [self.view addSubview: av] but that does not work. Neither does bringToFrontSubView:
Any help would be much appreciated
Peyman
The Alert code is fine (other than the release, mentioned in the comments).
[av show] is all that's required to show a view. You don't add UIAlertViews as subviews.
Call it after a delay of 0.1 sec [self performSelector:#selector(showAlert:) withObject:nil afterDelay:0.10];
Hope this will solve your problem.
With using autorelease the Alert View seems to be twice or 3 times. And for iOS4 it needs to be autoreleased otherwise it will crash.