How to disable a UIAlertView button with ios 7? - iphone

I have a simple view with a button linked with "showAlert" method. When I click on this button, it displays a UIAlertView.
Before, with ios 6, I was using the following code to disable a UIAlertView button :
- (IBAction)showAlert:(id)sender
{
myAlert = [[UIAlertView alloc] initWithTitle:#"" message:#"" delegate:self cancelButtonTitle:#"Retour" otherButtonTitles:#"Button1", #"Button2", #"Button3", #"Button4", nil];
[myAlert show];
for(UIView *aView in myAlert.subviews)
{
if ([[[aView class] description] isEqualToString:#"UIAlertButton"])
{
UIButton *aButton = (UIButton *)aView;
if ([aButton.titleLabel.text isEqualToString:#"Button2"])
aButton.enabled = NO;
}
}
}
Now, with ios 7, it does not work... Why ?

Since iOS7 it's not possible to add or manipulate the subviews or a UIAlertView, you need to create your own, sorry.
Subclass UIView to create your own UIAlertView or use a 3rd party library.

Adding a subview to UIAlertView is not possible from iOS 7.
The only way is to go for a custom UIView subclass which can act as UIAlertView.
Github and this answer may get you a solution.

You can disable 1st other Button of UIAlertView using delegate method
-(BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
{
return NO;
}
works in ios 7 also.

Related

Textfield in alertview not working in ios7?

I have an application in which I'm using a specific design for a reason. I put a text field in an alert view above an otherbutton with a background image. Everything is working fine in ios 6 version.
UIAlertView *av=[[UIAlertView alloc] initWithTitle:#"fdhdj" message:#" hdfjkhfjkhdk" delegate:self cancelButtonTitle:#"ok" otherButtonTitles:#" ",#"cancel",nil];
av.alertViewStyle = UIAlertViewStylePlainTextInput;
namefield = [[UITextField alloc] initWithFrame:CGRectMake(10.0,43.0, 264.0, 44.0)];
namefield.borderStyle = UITextBorderStyleNone;
namefield.background = [UIImage imageNamed:#"text_field_default.png"];
namefield.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
namefield.textAlignment = UITextAlignmentCenter;
//[namefield setBackgroundColor:[UIColor whiteColor]];
[av addSubview:namefield];
[namefield release];
av.tag=12;
av.delegate=self;
[av show];
[av release];
But now in ios 7, I heard you can't easily alter the view hierarchy of a UIAlertView.
One alternative for this case is to set
alert.alertViewStyle = UIAlertViewStylePlainTextInput
But can we add that text field in wherever we want? As in my case above the first otherbutton.can anybody help me?
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Enter Student Name" message:#"" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Save",nil];
[alertView setAlertViewStyle:UIAlertViewStylePlainTextInput];
[alertView show];
i used to do like this ,and its working very fine
This is my component to support addSubview with alertView in iOS7.
CXAlertView - Custom alert-view which allow you to add view as main content.
The simple answer to your question is NO, you can't change anything in this testField for the UIAlertViewStylePlainTextInput and you shouldn't.
This is from Apple:
The UIAlertView class is intended to be used as-is and does not
support subclassing. The view hierarchy for this class is private and
must not be modified.
And unfortunately what you heard I heard you can't easily alter the view hierarchy of a UIAlertView is wrong, you cannot alter the view hierarchy of a UIAlertView in iOS7 at all.
There are a good alternative on the web, you can check in cocoacontrols.com
You can't easily alter the view hierarchy of a UIAlertView in iOS 7. (Nor should you; the documentation specifically tells you not to.) Head over to the developer forums to see a long discussion about it.
One alternative in your case is to set alert.alertViewStyle = UIAlertViewStylePlainTextInput; This will add a text field for you. You can access it in the UIAlertView delegate callback by using UITextField *textField = [alertView textFieldAtIndex:0];.

UIAlertView displays textboxes and buttons

I used the following code to create a UIAlertView and add some components on it but the result is at the image :(( (image is here : http://i.stack.imgur.com/DTg02.png)
-(IBAction)login:(id)sender
{
UIAlertView *login = [[UIAlertView alloc]initWithTitle: #"Login first"
message:#"enter username and password please first" delegate:self cancelButtonTitle:#"cancel"otherButtonTitles:#"OK", nil];
k = [[UITextField alloc] initWithFrame:CGRectMake(20.0, 70.0, 200.0, 25.0)]; //<< it also displays wrong without this line
k.text = #"";
k.backgroundColor = [UIColor whiteColor];
k.clearButtonMode= UITextFieldViewModeWhileEditing;
k.keyboardType = UIKeyboardTypeAlphabet;
k.keyboardAppearance = UIKeyboardAppearanceAlert;
p = [[UITextField alloc] initWithFrame:CGRectMake(20.0, 100.0, 200.0, 25.0)];
p.text = #"";
p.backgroundColor = [UIColor whiteColor];
p.clearButtonMode = UITextFieldViewModeWhileEditing;
p.keyboardType = UIKeyboardTypeAlphabet;
p.keyboardAppearance = UIKeyboardAppearanceAlert;
[login addSubview:k];
[login addSubview:p];
[login show];
}
if you want to add multiple textField and Multiple Button on UIAlertView then follow the step :
step 1 :
#interface ViewController ()<UIAlertViewDelegate>
{
UITextField *textFieldOne,*textFieldTwo,*textFieldThird;
}
step 2 :
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Alert" message:#"Multiple TextField" delegate:nil cancelButtonTitle:#"NO" otherButtonTitles:#"YES", nil];
[alert addButtonWithTitle:#"CANCEL"];
alert.delegate=self;
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
textFieldOne=[[UITextField alloc]initWithFrame:CGRectMake(5, 0, 150, 20)];
[textFieldOne setPlaceholder:#"First Name"];
[myView addSubview:textFieldOne];
textFieldTwo=[[UITextField alloc]initWithFrame:CGRectMake(5,25, 150, 20)];
[textFieldTwo setPlaceholder:#"Middle Name"];
[myView addSubview:textFieldTwo];
textFieldThird=[[UITextField alloc]initWithFrame:CGRectMake(5,50, 150, 20)];
[textFieldThird setPlaceholder:#"Last Name"];
[myView addSubview:textFieldThird];
[alert setValue:myView forKey:#"accessoryView"];
[alert show];
step 3 :
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:#"YES"])
{
NSLog(#"Button YES");
NSLog(#"TextFiledOne Text = %#",textFieldOne.text);
NSLog(#"TextFiledTwo Text = %#",textFieldTwo.text);
NSLog(#"TextFiledThree Text = %#",textFieldThird.text);
}
else if([title isEqualToString:#"NO"])
{
NSLog(#"Button NO");
}
else
{
NSLog(#"Cancel is click");
}
}
A UIAlertView is no thought for additional text input. You could use instead a UIActionSheet as it is explained here.
There is no point adding to the code that has already been added on here as it is good enough already and there are some good alternatives given. What I am going to do is tell you why you shouldn't be adding your own UITextFields to a UIAlertView using addSubview:.
Basically Apple have made the UIAlertView class to be used as is and the view hierarchy for this class is private.
Subclassing Notes
The UIAlertView class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified.
Subclassing note taken from UIAlertView Apple documentation.
In essence what this means is that if you use the addSubview: method on a UIAlertView then you are in essence altering something that Apple as indicated as being private and your app would get rejected from the Apple App Review Process for rule 2.5.
2.5 Apps that use non-public APIs will be rejected
You might be asking yourself why does that method even exist then for UIAlertView surely because its there we can use it. Well NO the reason it is there is because the UIAlertView class is itself is a subclass of UIView which is where the addSubview: method is declared. Unfortunately there is no why to stop a instance of UIAlertView from actually calling that method. So what Apple have done is they have overridden the addSubview: method and all it does is it returns. So this method makes it do nothing and any views you pass to this method will never get added, as it never calls [super addSubview:view];.
So when it comes to UIAlertViews there are two things that you shouldn't be doing and these are:
Subclass UIAlertView like #interface MYAlertView : UIAlertView this is subclassing and is not allowed.
Alter View Hierarchy like [alertView addSubview:view];
However there is one point I should make, whilst we aren't allowed to subclass UIAlertView we are still allowed to make categories for it like #interface UIAlertView (MyCategory) as this is not classed as subclassing it is known as a class category or class extension (I've also heard it called a class provider before).
It should also be noted that if you are developing for iOS8 and above you should be using UIAlertController as the UIAlertView has been deprecated.
Important:
UIAlertView is deprecated in iOS 8. (Note that UIAlertViewDelegate is also deprecated.) To create and manage alerts in iOS 8 and later, instead use UIAlertController with a preferredStyle of UIAlertControllerStyleAlert.
So I'd either use one of the custom classes mentioned in the other answers or move to use UIAlertController or if you have the time make your own custom alert view.
I hope this explanation helps you understand UIAlertViews more.
Don't go for all the bluffs. Just use the following code:
[login setAlertViewStyle:UIAlertViewStyleLoginAndPasswordInput];
And to handle the inputs of the user, use this:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if([[alertView textFieldAtIndex:0].text isEqual:#"UserName"]&&[[alertView textFieldAtIndex:1].text isEqual:#"PassWord"])
{
//do your stuff here
[adminLoginButton setTitle:#"Logout" forState:UIControlStateNormal];
[adminLoginButton setImage:[UIImage imageNamed:#"Logout.png"] forState:UIControlStateNormal];
}
else
{
UIAlertView *errorMessage = [[UIAlertView alloc]initWithTitle:#"Authentication Error" message:#"Input is wrong" delegate:self cancelButtonTitle:#"Okay" otherButtonTitles: nil];
[errorMessage show];
}
}

UIAlertView choice causing resignFirstResponder to fail

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!

Dismissing the keyboard for a UITextField in UIAlertView

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];
}

iphone to ipad, iphone 4 uialertview problems

So I've upgraded the code to the ipad (i.e. converted to a universal app). However, the UIAlertview rendering seems to be off for IOS4. Instead of being positioned in the middle, it jumps up and is displayed on top, with half the box cut off. Same goes for landscape orientation.
It is my understanding that the UIalertview is always set in the middle? I looked through the code and I did not set up the frame/position anywhere in the code. This only happens for 4.0, on both the iphone 4 and the itouch running 4.0. Every other version is fine, including the ipad. Any thoughts?
Thanks.
Seems to be a bug. I also had the Problem on iPad with iOS 3.2.
Solution:
a) Check your app state:
In iOS 4 just use
[UIApplication sharedApplication].applicationState
Older iOS: Store your app state manually:
-(void)applicationWillResignActive:(UIApplication *)application
{
self.appIsInBackground = YES;
}
-(void)applicationWillTerminate:(UIApplication *)application
{
self.appIsInBackground = YES;
}
-(void)applicationDidBecomeActive:(UIApplication *)application
{
// Open your UIAlert here if self.appIsInBackground == YES;
self.appIsInBackground = NO;
}
b) open the UIAlert after the app did become active, as shown above in the comments.
Does your alert have any Textfields added ?
Because in 4.0+ iOS scrolls the alertview to visible part if you have a textfield in the alertview.
I have the same problem for iPad 3.2 when application resign active and in that time alert is shown that alert will be shown on top left corner. So i fixed using following code in the method -(void)applicationDidBecomeActive:(UIApplication *)application
//Check that key window is alert view
if ([[[UIApplication sharedApplication].keyWindow description] hasPrefix:#"<_UIAlertOverlayWindow"]) {
//Yes then check for subviews tht are alertViews
UIWindow *alertViewWindow = [UIApplication sharedApplication].keyWindow;
NSArray *subViews = [alertViewWindow subviews];
for (UIView *subview in subViews)
{
if ([subview isKindOfClass:[UIAlertView class]])
{
//Retain it
UIAlertView *alertView = (UIAlertView *)[subview retain];
//Now dismiss it and then show it again
[alertView dismissWithClickedButtonIndex:0 animated:NO];//Here ClickedButtonIndex must be according to cancel button
//Show the alert view again
[alertView show];
//Release previsous retained object
[alertView release];
}
}
}