I'm trying to get text from an alert view and add it to my mutable array to list in a table view. I realize there is a similar question that was posted a few months ago, but I dont understand how to utilize the given answer.
-(IBAction)insert {
UIAlertView* dialog = [[UIAlertView alloc] init];
[dialog setDelegate:self];
[dialog setTitle:#"Enter Name"];
[dialog setMessage:#" "];
[dialog addButtonWithTitle:#"Cancel"];
[dialog addButtonWithTitle:#"OK"];
UITextField *nameField = [[UITextField alloc] initWithFrame:CGRectMake(20.0, 45.0, 245.0, 25.0)];
[nameField setBackgroundColor:[UIColor whiteColor]];
[dialog addSubview:nameField];
[dialog show];
[data addObject:[nameField text]];
[mainTableView reloadData];
However my app crashes because it says I'm attempting to insert a nil object at index 0. What am I doing wrong?
EDIT: Ok I think I'm missing a method to handle the alertview. So I found this:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
NSString *buttonTitle=[alertView buttonTitleAtIndex:buttonIndex];
if([buttonTitle isEqualToString:#"Cancel"]) {
return;
}
else if([buttonTitle isEqualToString:#"Ok"]) {
[data addObject:nameField.text];
}
Now I just need to connect the pieces, but not sure how.
A common mistake that people make when using a UIAlertView is that they think that sending it a show message will block the main thread. It does not. Your code continues to execute, even though there is an alert on the screen. Thus, no value exists for the UITextField that you have passed in.
What you need to do is implement the UIAlertViewDelegate in your UIViewController to grab whatever a user has entered into the text field. That said, you still have to check for a nil value, because if you don't type anything in, the text value will be nil.
UPDATE: This answer was posted before Apple created an API for adding a UITextField to an alert through the UIAlertViewStyle. Here is the updated code, borrowed from #matt
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Enter Name"
message:#" "
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
Then, in the UIAlertViewDelegate call back:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
NSString *name = [alertView textFieldAtIndex:0].text;
// Insert whatever needs to be done with "name"
}
}
You don't need to add your own text field to the AlertView but instead set the appropriate style
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Enter Name"
message:#" "
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
Then access the entered text after OK (button 1) was pressed
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1) {
NSString *name = [alertView textFieldAtIndex:0].text;
// name contains the entered value
}
}
Don't try to add a UITextView on a UIAlertView or else Apple might reject your app.
I already used the same kind of functionality in my app. But Apple REJECTED MY APP due to the use of UITextView in UIAlertView.
– alertView:clickedButtonAtIndex: is a delegate method of UIAlertView. Just add the method you defined in your edit to your controller implementation and you should be good to go, since you already set the controller to be the AlertView's delegate.
Also add to your class header, to avoid any delegate related warnings, ie:
#interface MyViewController : UIViewController <UIAlertViewDelegate> {
...
};
Don't forget to remove [data addObject:[nameField text]]; and [mainTableView reloadData]; from the insert method.
UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle:#"Alert title"
message:#"alert message"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Ok", nil];
[myAlert addTextFieldWithValue:nil label:#"<place holder>"];
[[myAlert textField] setTextAlignment:UITextAlignmentCenter];
[[myAlert textField] becomeFirstResponder];
[myAlert show];
[myAlert release];
myAlert = nil;
No need to add a custom textfield. You can directly add using addTextFieldWithValue method.
Related
I have a class name viewController and it has the following code below and it works fine. However, when I call check from my subclass controller it doesn't work the way I want it to.The UIAlertView shows up, but it isn't able to detect when button index 0 is touched.Any workaround for this.
-(void)check{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"You Lose!"
message:#"Play Again?"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:#"OK", nil];
[alert show];
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) { // and they clicked OK.
ViewController*myNewVC = [[ViewController alloc] init];
[self presentModalViewController:myNewVC animated:NO];
}
}
Add UIAlertViewDelegate in your subclass .h file like bellow..
#interface yourSubClassViewController :UIViewController <UIAlertViewDelegate>{
/// your code
}
#end
The Cancel button will be the index "0", Try for index==1.
Use this method:
-(void)check{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"You Lose!"
message:#"Play Again?"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:#"PopUp", nil];
[alert show];
}
- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
NSLog("Cancel Button clicked);
}
else if (buttonIndex == 1) {
ViewController*myNewVC = [[ViewController alloc] init];
[self presentModalViewController:myNewVC animated:NO];
}
Don't use cancel button. Use two buttons otherButtonTitles and use the buttons index == 1 and button index == 2 . That may help.
You need to set the delegate to your subclass.
-(void)check:(id)delegate{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"You Lose!"
message:#"Play Again?"
delegate:delegate
cancelButtonTitle:#"OK"
otherButtonTitles:#"OK", nil];
[alert show];
}
and you call it [self check:self];
I am new to iOS.
I am working on alertviews. Here is my code. Here there are 2 alertviews: successfulallert and unsuccessfulallert for login page. I am using alertview delegate also here, it will work for both alertviews but I want to work only for successful alertview and navigation should be done only for successful alertview. If anybody knows this please help me.
NSString *responseOfResult = [[NSString alloc]initWithString:[result response]];
NSRange match;
// NSLog(#"string= %#", str);
match = [responseOfResult rangeOfString: #"successful"];
if(match.location == NSNotFound)
{
UIAlertView *unsuccessfulAllert = [[UIAlertView alloc]
initWithTitle:#"Alert"
message:responseOfResult
delegate:self
cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[unsuccessfulAllert show];
}
else {
UIAlertView *successfulAllert = [[UIAlertView alloc]
initWithTitle:#"Message" message:#"Login successful." delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[successfulAllert show];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if(buttonIndex == 0){
[[self navigationController]pushViewController:registerUserScreen animated:YES];
}
}
Why don't you put "OK" as cancelButtonTitle? Everything will be handled automatically.
UIAlertView *successfulAllert = [[UIAlertView alloc]
initWithTitle:#"Message" message:#"Login successful." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[successfulAllert show];
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if(buttonIndex == 0){
//POP here with this:
[self.navigationController pushViewController:addItemView animated:NO];
}
}
NSString *responseOfResult = [[NSString alloc]initWithString:[result response]];
NSRange match;
// NSLog(#"string= %#", str);
match = [responseOfResult rangeOfString: #"successful"];
if(match.location == NSNotFound)
{
UIAlertView *unsuccessfulAllert = [[UIAlertView alloc]
initWithTitle:#"Alert"
message:responseOfResult
delegate:self
cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[unsuccessfulAllert setTag:1];
[unsuccessfulAllert show];
}
else {
UIAlertView *successfulAllert = [[UIAlertView alloc]
initWithTitle:#"Message" message:#"Login successful." delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[successfulAllert setTag:2];
[successfulAllert show];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if(alertView.tag == 2)
{
[[self navigationController]pushViewController:registerUserScreen animated:YES];
}
else
{
//[[self navigationController]pushViewController:registerUserScreen animated:NO];
// OR
return;
}
}
You have many ways to correct your code, the first and very common is to use the tag property (integer) of the UIView. Since UIAlertview inherits from UIView, it has the tag property, so each time you want create an alert (or a view), set the tag and the check your condition like:
...
alert.tag=1;
[alert show];
then to know wich alert is calling the callback:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if(alertView.tag==theTagOfYourAlert){
//do your stuff
}
}
another way, in your case, could be:
if([alertView.title isEqualToString:#"Alert"]){
//do your stuff
}
}
Add tag to the two alert views and check for tag in alert view delegate.
Sample code:
NSString *responseOfResult = [[NSString alloc]initWithString:[result response]];
NSRange match;
// NSLog(#"string= %#", str);
match = [responseOfResult rangeOfString: #"successful"];
if(match.location == NSNotFound)
{
UIAlertView *unsuccessfulAllert = [[UIAlertView alloc]
initWithTitle:#"Alert"
message:responseOfResult
delegate:self
cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[unsuccessfulAllert setTag:1];
[unsuccessfulAllert show];
}
else {
UIAlertView *successfulAllert = [[UIAlertView alloc]
initWithTitle:#"Message" message:#"Login successful." delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[successfulAllert setTag:2];
[successfulAllert show];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if(alertView.tag==2 && buttonIndex == 0){
[[self navigationController]pushViewController:registerUserScreen animated:YES];
}
Yes the delegate would work for both the alertviews but you can assign a tag to each alertview Object and check for the tag in the delegate and then perform event if the tag for that particular AlertView onject matches.If u need code , i will provide.
For things like Login status updates, you might want to have the "Login Successful" message disappear automatically. Try this instead:
https://github.com/camclendenin/flashbox
This works nicely and comes in handy for situations like this. Plus you don't have to deal with all the clutter involved with UIAlertViews.
This piece of code which is supposed to show an alert window with a text input:
self.alert = [[UIAlertView alloc] initWithTitle:#"Hello" message:#"How are you?" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil];
self.alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[self.alert show];
Causes this error:
Thread 7: Program received signal: "EXC_BAD_ACCESS"
This is how self.alert is defined:
#interface MyClass : NSObject
{
UIAlertView *alert;
id <MyClassDelegate> __unsafe_unretained delegate;
}
#property (nonatomic, retain) UIAlertView *alert;
#property (unsafe_unretained) id <MyClassDelegate> delegate;
The problem is maybe because of the customize.
I do not know why, but appear to me that the problem is because of the use of threads + customize of your alert.
Can you try to show this alert on the main thread? What happen?
You probably get an error in this line:
self.alert.alertViewStyle = UIAlertViewStylePlainTextInput;
What you need to do if yes, is perform this in the main thread.
- (void) yourMethod{
[self performSelectorOnMainThread:#selector(yourMethod2) withObject:nil waitUntilDone:NO];
}
- (void) yourMethod2{
self.alert = [[UIAlertView alloc] initWithTitle:#"Hello" message:#"How are you?" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil];
self.alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[self.alert show];
}
Sorry to can't help you more than that, but I do not know exactly what happen, but I already read about issues when editing things to show, in other threads.
Hope it help you!
The EXC_BAD_ACCESS is caused by accessing a released object. To avoid this make your call to UIAlertView kind of modal:
Function body:
-(void)checkSaving
{
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Do you want to add these results to your database?"
message:#"\n\n"
delegate:self
cancelButtonTitle:#"No"
otherButtonTitles:#"Save", nil];
alert.alertViewStyle = UIAlertViewStyleDefault;
[alert show];
//this prevent the ARC to clean up :
NSRunLoop *rl = [NSRunLoop currentRunLoop];
NSDate *d;
d= (NSDate*)[d init];
while ([alert isVisible])
{
[rl runUntilDate:d];
}
}
Your choice result:
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
// the user clicked one of the OK/Cancel buttons
if (buttonIndex == 1)//Save
{
//do something
}
if (buttonIndex == 0)//NO
{
//do something
}
}
Register the functions in the interface declaration:
#interface yourViewController ()
-(void)checkSaving
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
//...
#end
To call:
[self checkSaving];
I wish this will help you.
I'm using logos for iPhone (MobileSubstrate addons), with a .h file for my
#interface MyClass : NSObject <UIAlertViewDelegate>
and the
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if(buttonIndex == 0) {
is in the .m, but nothing is working, when tapping the buttons on the alert, it doesn't invoke what I have set for each buttonIndex.
Thanks.
Edit: Here's what I've got;
#import "Tweak.h"
%hook ASApplicationPageHeaderView
- (void)_showPurchaseConfirmation {
UIAlertView *alert = [[UIAlertView alloc] init];
[alert setTitle:#"title"];
[alert setMessage:#"message"];
[alert setDelegate:self];
[alert addButtonWithTitle:#"button 1"];
[alert addButtonWithTitle:#"continue"];
[alert show];
[alert release];
}
- (void)alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) { //also tried (UIAlertView *)alertView
UIAlertView *lol = [[UIAlertView alloc] init];
[lol setTitle:#"button 1"];
[lol setMessage:#"button 1"];
[lol setDelegate:self];
[lol addButtonWithTitle:#"lol"];
[lol show];
[lol release];
} else {
%orig;
}
}
%end
You'll most likely need to register your class as the delegate at some point using something along the lines of:
[yourAlertViewObject setDelegate:self];
As the UIAlertViewDelegate Protocol Reference docs say (emphasis mine):
If you add your own buttons or
customize the behavior of an alert
view, implement a delegate conforming
to this protocol to handle the
corresponding delegate messages. Use
the delegate property of an alert view
to specify one of your application
objects as the delegate.
Define your alert within that class and declare the alert delegate to self hope it start working to you
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Alert View "
"
message:#"Would you like to do something?"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Button1", #"Button2", nil];
[alert show];
[alert release];
You just need to put %new in front of the alertView delegate:
%new
-(void) alertView:...
Is it possible to show an alertview with a textbox inside like the AppStore app.
It asks for password in such a dialog.
I've seen atleast a couple of other third party apps using it. Is it a private API?
Here's an "Apple Approved" way of doing it from Tharindu Madushana. I got it from his comment in this page: http://iosdevelopertips.com/undocumented/alert-with-textfields.html
// Ask for Username and password.
UIAlertView *alertview = [[UIAlertView alloc] initWithTitle:#"Twitter Details!" message:#"\n \n \n" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil];
// Adds a username Field
UITextField *utextfield = [[UITextField alloc] initWithFrame:CGRectMake(12.0, 45.0, 260.0, 25.0)];
utextfield.placeholder = #"Username";
[utextfield setBackgroundColor:[UIColor whiteColor]];
[alertview addSubview:utextfield];
// Adds a password Field
UITextField *ptextfield = [[UITextField alloc] initWithFrame:CGRectMake(12.0, 80.0, 260.0, 25.0)];
ptextfield.placeholder = #"Password";
[ptextfield setSecureTextEntry:YES];
[ptextfield setBackgroundColor:[UIColor whiteColor]]; [alertview addSubview:ptextfield];
// Move a little to show up the keyboard
CGAffineTransform transform = CGAffineTransformMakeTranslation(0.0, 80.0);
[alertview setTransform:transform];
// Show alert on screen.
[alertview show];
[alertview release];
//...
// Don't forget to release these after getting their values
[utextfield release];
[ptextfield release];
And finally to get the text back
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0)
return; //Cancel
UITextField *field = (UITextField *)[[alertView subviews] lastObject];
NSLog (#"%#", field.text);
}
Yes, it's undocumented. To add a text field to UIAlertView, use addTextFieldWithValue: label: method. You call with the default text as the first argument and the text that displays in an empty field as the second. Having done that, you can access the field via using textFieldAtIndex:n - see below.
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: #"Who are you?"
message:#"Give your full name"
delegate:self cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil];
[alert addTextFieldWithValue:#""label:#"Name"];
// Customise name field
UITextField* name = [alert textFieldAtIndex:0];
name.clearButtonMode = UITextFieldViewModeWhileEditing;
name.keyboardType = UIKeyboardTypeAlphabet;
name.keyboardAppearance = UIKeyboardAppearanceAlert;
[alert show];
The next snippet shows how to retrieve the value in the name field:
NSLog("Name is %#", [[modalView textFieldAtIndex:0] text]);
This is a really old questions with really old answers.
This is a sample of how I get a UITextfield into a UIAlertView since ios 5:
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"New List Name" message:#"" delegate:nil cancelButtonTitle:#"Cancel" otherButtonTitles:#"Continue", nil];
message.alertViewStyle = UIAlertViewStylePlainTextInput;
self.alertTextField = [message textFieldAtIndex:0];
self.alertTextField.keyboardType = UIKeyboardTypeAlphabet;
message.delegate = self;
[message show];
[self.alertTextField becomeFirstResponder];
where alertTextField was set up like this:
#property (nonatomic, strong) UITextField *alertTextField;
Jeff Lamarche posted some sample code on his blog to do just this. The formatting looked a bit wonky when I tried it but it's probably a good starting point.