How to get text from textFieldDidEndEditing? - ios

Probably a simple answer to this,
How can i pass the textField.text from an UIAlertView that has a textfield in it
to a -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
i tried to create a property NSString and make it equal to textField.text and tried to NSLog it and it came back NULL

Updated Answer
To retrieve the text of a text field in the UIAlertView you can use the textFieldAtIndex: method. You don't need to involve the text field delegate at all.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
UITextField *textField = [alertView textFieldAtIndex:0]; // adjust the index if you have more than one text field.
NSLog(#"Text: %#", textField.text);
}
Original Answer
You have a couple of options here.
Option 1
Store a reference to the text field as a property, it seems likely you are already doing this.
#property (nonatomic, weak) IBOutlet UITextField *textField;
This can then be accessed directly from the UIAlertView delegate method, assuming the delegate is the same object that has the reference to the text field:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
NSLog(#"Text: %#", self.textField.text);
}
Option 2
If for some reason you don't have a reference to your text field you can get it from the textFieldDidEndEditing: delegate method, firstly create a property to store the text:
#property (nonatomic, copy) NSString *textFieldText;
Then update that when the text field delegate method is called.
- (void)textFieldDidEndEditing:(UITextField *)textField {
self.textFieldText = textField.text;
}
Then you can access this property in the UIAlertView delegate method:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
NSLog(#"Text: %#", self.textFieldText);
}

This code is working for me:
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:#"" message:[NSString stringWithFormat:#"Do you want to call?"] delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
UITextField * alertTextField = [alert textFieldAtIndex:0];
alertTextField.keyboardType = UIKeyboardTypeNumberPad;
[alertTextField setTextAlignment:NSTextAlignmentCenter];
[alert show];
and delegates:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex==1) {
return;
}
UITextField *title1;// = [alertView textFieldAtIndex:0];
title1= [alertView textFieldAtIndex:0];
NSString *messageStr = title1.text;
if ([messageStr isEqualToString:#""]) {
return;
}}

you just declare NSString object in
#interface LoginDialogVC ()
{
NSString strText;
}
#end
#implementation LoginDialogVC
-(void)textFieldDidEndEditing:(UITextField *)textField {
strText = textField.text;
}
after that use strText whenever you want to use.

Related

Why is this delegate not triggering is a mystery

I have developed this class that is basically a UIAlertView with an input field that runs on blocks. So, whatever the user does on the alertView (click cancel, ok, or fill the text), returns to a block:
HEADER
typedef void (^onClickBlock)(NSInteger buttonIndex, NSString *textoInput);
#interface AlertViewBlocoComInput : NSObject
- (void)mostrarAlertViewBlocoComTitulo:(NSString *)titulo
mensagem:(NSString *)mensagem
tituloBotaoCancel:(NSString *)tituloCancel
outrosBotoesArray:(NSArray *)titulosOutrosBotoes
inputComPlaceHolder:(NSString *)textoPlaceholder
comBlocoExecucao:(onClickBlock)bloco;
#end
IMPLEMENTATION
#interface AlertComBloco : UIAlertView
#property (nonatomic, copy) onClickBlock runOnClickBlock;
#end
#implementation AlertComBloco
#end
#interface AlertViewBlocoComInput () <UIAlertViewDelegate>
#end
#implementation AlertViewBlocoComInput
- (void)mostrarAlertViewBlocoComTitulo:(NSString *)titulo
mensagem:(NSString *)mensagem
tituloBotaoCancel:(NSString *)tituloCancel
outrosBotoesArray:(NSArray *)titulosOutrosBotoes
inputComPlaceHolder:(NSString *)textoPlaceholder
comBlocoExecucao:(onClickBlock)bloco
{
AlertComBloco *alerta = [[AlertComBloco alloc] initWithTitle:titulo
message:mensagem
delegate:self
cancelButtonTitle:tituloCancel
otherButtonTitles:nil];
alerta.runOnClickBlock =bloco;
// adicionar os outros botões
for (NSString *umOutroBotao in titulosOutrosBotoes) {
[alerta addButtonWithTitle:umOutroBotao];
}
[alerta setAlertViewStyle:UIAlertViewStylePlainTextInput];
UITextField *input = [alerta textFieldAtIndex:0];
input.placeholder = textoPlaceholder;
[alerta show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
AlertComBloco *alerta = (AlertComBloco *)alertView;
onClickBlock bloco = alerta.runOnClickBlock;
UITextField *input = [alertView textFieldAtIndex:0];
if (bloco) {
bloco(buttonIndex, input.text);
}
}
#end
I run it, it shows the alertView with the message, placeholder, perfect. I click cancel or fill the text and press ok and the alertview:clickedButtonAtIndex: is never triggered. I am not seeing why.
thanks
You can directly subclass UIAlertView and add your own initializer. I have abstracted your classes to a single subclass of UIAlertView and it works fine. Please see my posts below,
typedef void (^onClickBlock)(NSInteger buttonIndex, NSString *textoInput);
#interface AlertComBloco : UIAlertView<UIAlertViewDelegate>
#property (nonatomic, copy) onClickBlock runOnClickBlock;
#end
#implementation AlertComBloco
- (id)initWithTitulo:(NSString *)titulo mensagem:(NSString*)mensagem tituloBotaoCancel:(NSString*)tituloCancel outrosBotoesArray:(NSArray *)titulosOutrosBotoes inputComPlaceHolder:(NSString *)textoPlaceholder
comBlocoExecucao:(onClickBlock)bloco{
if(self = [self initWithTitle:titulo message:mensagem delegate:self cancelButtonTitle:tituloCancel otherButtonTitles:nil, nil]){
_runOnClickBlock = bloco;
for (NSString *umOutroBotao in titulosOutrosBotoes) {
[self addButtonWithTitle:umOutroBotao];
}
[self setAlertViewStyle:UIAlertViewStylePlainTextInput];
UITextField *input = [self textFieldAtIndex:0];
input.placeholder = textoPlaceholder;
}
return self;
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
UITextField *input = [alertView textFieldAtIndex:0];
if (self.runOnClickBlock) {
self.runOnClickBlock(buttonIndex, input.text);
}
}
#end
Then, you could call it with the block in your view controller just like this,
- (void)showAlert:(id)sender{
AlertComBloco *alertCombo = [[AlertComBloco alloc] initWithTitulo:#"Hi" mensagem:#"Custom Alert" tituloBotaoCancel:#"Cancel" outrosBotoesArray:#[#"Other"] inputComPlaceHolder:#"Placeholder" comBlocoExecucao:^(NSInteger buttonIndex, NSString *textoInput) {
NSLog(#"Button at index %ld, with text %#", (long)buttonIndex, textoInput);
}];
[alertCombo show];
}
You haven't shown us how you're calling this but most likely your AlertViewBlocoComInput is a local variable that has fallen out of scope and is therefore deallocated before the user completes their input. You can demonstrate this by temporarily adding a dealloc method that will tell you when the object is deallocated.
- (void)dealloc {
NSLog(#"%s", __PRETTY_FUNCTION__);
}
In terms of fixing this, you could make your AlertViewBlocoComInput instance a class property, so it won't be released until you manually nil it. Or you can make AlertViewBlocoComInput maintain a strong reference to itself until clickedButtonAtIndex is called.
Or, easiest, leverage the fact that UIAlertView already retains itself, so you can retire AlertComBloco altogether, folding it into AlertViewBlocoComInput:
typedef void (^onClickBlock)(NSInteger buttonIndex, NSString *textoInput);
#interface AlertViewBlocoComInput : UIAlertView <UIAlertViewDelegate>
- (instancetype)initComTitulo:(NSString *)titulo
mensagem:(NSString *)mensagem
tituloBotaoCancel:(NSString *)tituloCancel
outrosBotoesArray:(NSArray *)titulosOutrosBotoes
inputComPlaceHolder:(NSString *)textoPlaceholder
comBlocoExecucao:(onClickBlock)bloco;
#property (nonatomic, copy) onClickBlock runOnClickBlock;
#end
#implementation AlertViewBlocoComInput
- (instancetype)initComTitulo:(NSString *)titulo
mensagem:(NSString *)mensagem
tituloBotaoCancel:(NSString *)tituloCancel
outrosBotoesArray:(NSArray *)titulosOutrosBotoes
inputComPlaceHolder:(NSString *)textoPlaceholder
comBlocoExecucao:(onClickBlock)bloco
{
self = [super initWithTitle:titulo message:mensagem delegate:self cancelButtonTitle:tituloCancel otherButtonTitles:nil];
if (self) {
self.runOnClickBlock =bloco;
// adicionar os outros botões
for (NSString *umOutroBotao in titulosOutrosBotoes) {
[self addButtonWithTitle:umOutroBotao];
}
[self setAlertViewStyle:UIAlertViewStylePlainTextInput];
UITextField *input = [self textFieldAtIndex:0];
input.placeholder = textoPlaceholder;
}
return self;
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (self.runOnClickBlock) {
UITextField *input = [alertView textFieldAtIndex:0];
self.runOnClickBlock(buttonIndex, input.text);
}
}
#end
And you'd call it like so:
AlertViewBlocoComInput *obj = [[AlertViewBlocoComInput alloc] initComTitulo:#"title" mensagem:#"message" tituloBotaoCancel:#"OK" outrosBotoesArray:nil inputComPlaceHolder:#"Placeholder" comBlocoExecucao:^(NSInteger buttonIndex, NSString *textoInput) {
// do whatever you want with `buttonIndex` and `textoInput` here
//
// NSLog(#"%ld %#", (long)buttonIndex, textoInput);
}];
[obj show];

Multiple UIAlertViews to Enter Data

I have two buttons that will pop up an alertview with textfield to input data. However, only certain characters are allowed in each of the two textfields. Somehow, if I press the second button, the character set from the first button is used. What's going on here?
Also, what would be a more elegant form of inputting data without having to use an alertview? Could I use a modal view? If so, how?
- (IBAction)editRate
{
if(!self.powerOn) return;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Edit Jail Fee Rate"
message:#"Enter New Daily Rate"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Ok", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[[alert textFieldAtIndex:0] setKeyboardType:UIKeyboardTypeNumberPad];
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != alertView.cancelButtonIndex)
{
UITextField *field = [alertView textFieldAtIndex:0];
field.placeholder = #"Enter New Rate";
NSCharacterSet * set = [[NSCharacterSet characterSetWithCharactersInString:#"0123456789."] invertedSet];
if ([field.text rangeOfCharacterFromSet:set].location != NSNotFound)
{
UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Only numbers are allowed in this field."delegate:self cancelButtonTitle:#"OK"otherButtonTitles:nil];
[errorAlert show];
FeeRate.text=#"0.00";
}
else
{
FeeRate.text = field.text;
[[NSUserDefaults standardUserDefaults] setObject:field.text forKey:RATE_KEY];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
else
{
}
}
- (IBAction)editDate
{
if(!self.powerOn) return;
UIAlertView *alertDate = [[UIAlertView alloc] initWithTitle:#"Edit Jail Fee Date"
message:#"Enter New Date"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Ok", nil];
alertDate.alertViewStyle = UIAlertViewStylePlainTextInput;
[[alertDate textFieldAtIndex:0] setKeyboardType:UIKeyboardTypeNumberPad];
[alertDate show];
}
- (void)alertDate:(UIAlertView *)alertDate clickedButtonAtIndex:(NSInteger)buttonIndex2
{
if (buttonIndex2 != alertDate.cancelButtonIndex)
{
UITextField *fieldDate = [alertDate textFieldAtIndex:0];
fieldDate.placeholder = #"Enter New Date";
NSCharacterSet * setnew = [[NSCharacterSet characterSetWithCharactersInString:#"0123456789/"] invertedSet];
if ([fieldDate.text rangeOfCharacterFromSet:setnew].location != NSNotFound)
{
UIAlertView *errorAlert1 = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Only numbers and slashes are allowed in this field."delegate:self cancelButtonTitle:#"OK"otherButtonTitles:nil];
[errorAlert1 show];
FeeDate.text=#"00/00/0000";
}
else
{
FeeDate.text = fieldDate.text;
[[NSUserDefaults standardUserDefaults] setObject:fieldDate.text forKey:DATE_KEY];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
else
{
}
}
When a UIAlertView is dismissed then a function called
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
is called.
So, both your alert views call this function.
One way to tell which alertView is calling it, you could create an ivar or better two properties like this:
#property (nonatomic, strong) UIAlertView *rateAlert;
#property (nonatomic, strong) UIAlertView *dateAlert;
and you should initialize like this:
[self setRateAlert:[[UIAlertView alloc] initWithTitle...
[self.rateAlert show];
and
[self setDateAlert:[[UIAlertView alloc] initWithTitle...
[self.dateAlert show];
and then:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (alertView==self.rateAlert) {
//do whatever for rateAlert
} else {
//do whatever with dateAlert
}
}

Retrieving index path from table view

i am trying to replace an object at in an array by replacing it with the text returned from an alert view.
so far i have:
int selected = indexPath.row;
and for my alertview delegate method.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (alertView.tag == 1) {
[myMutableArray replaceObjectAtIndex:selected withObject:[[alertView textFieldAtIndex:0] text]];
[_tableView reloadData];
}
}
i keep getting an error of
Incompatible integer to pointer conversion assigning to 'NSInteger *' (aka 'long *') from 'NSInteger' (aka 'long')
The error you see comes from the fact that you put a * somewhere before the NSInteger variable.
Without knowing what the rest of your code looks like, you could try this in your ViewController.m file. It sets the text of a label and replaces an object in a mutable array with the text from the alert view when the "OK" button is pressed.
#import "ViewController.h"
#interface ViewController () <UIAlertViewDelegate>
#property (strong,nonatomic) NSMutableArray *mutArray;
#property (weak,nonatomic) IBOutlet UILabel *label;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *array = #[#"item1",#"item2",#"item3"];
self.mutArray = [[NSMutableArray alloc] init];
self.mutArray = [array mutableCopy];
}
- (IBAction)showAlert:(id)sender {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"My Alert Example"
message:#"message here"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK",nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
int selected = 1;
if (buttonIndex != alertView.cancelButtonIndex) {
NSLog(#"ok button");
UITextField *textField = [alertView textFieldAtIndex:0];
self.label.text = textField.text;
[self.mutArray replaceObjectAtIndex:selected withObject:textField.text];
NSLog(#"mutArray is %#",self.mutArray);
} else {
NSLog(#"cancel button");
}
}
#end
Since it looks like you're using a UITableView, in your case you would have int selected = indexPath.row instead of int selected = 1.

alertViewShouldEnableFirstOtherButton not called

I want to show UIAlertview With textfield. And if User has not entered valid emai id then ok button of UIAlertview will be disable.
I know How to show UIAlertview and disable UIAlertview Ok button ..
My problem is -(BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView not called thats why button is enabled.
But When user press Ok button then
- (void)alertView:(UIAlertView
*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
is called.
Here is my code ,
-(IBAction)forgotpassBtnclicked:(id)sender
{
UIAlertView *alertview=[[UIAlertView alloc]initWithTitle:#"" message:#"" delegate:self cancelButtonTitle:#"ok" otherButtonTitles:nil, nil];
[alertview setAlertViewStyle:UIAlertViewStylePlainTextInput];
UITextField *textField=[alertview textFieldAtIndex:0];
textField.placeholder=#"enter your email id";
[alertview show];
}
#pragma mark Alertview delgate
- (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
{
UITextField *text1=[alertView textFieldAtIndex:0];
BOOL flag=[self validateEmail:text1.text];
return flag;
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
}
#pragma mark Email Validation
- (BOOL) validateEmail: (NSString *) email
{
NSString *emailRegex = #"[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
NSPredicate *emailTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", emailRegex];
// return 0;
return [emailTest evaluateWithObject:email];
}
i don't understand what am i doing wrong?..
Thanks in Advance...
UIAlertViewDelegate documentation says for alertViewShouldEnableFirstOtherButton: method,
Sent to the delegate to determine whether the first non-cancel button ion the alert should be enabled.
You are creating the alert with cancel button as #"ok", since non-cancel buttons is nil the method is not getting called. Instead try following,
UIAlertView *alertview=[[UIAlertView alloc]initWithTitle:#"" message:#"" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok", nil];
Also, user should have option to cancel the alert without having to enter text. It is good user experience to have a cancel button.

UIAlertView textfield keyboard type

I having problem in displaying the textfield keyboard type in the alertview. I want to display numberpad keyboard but it not working.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
switch (alertView.tag) {
case 1:
if (buttonIndex == 0) {
UITextField *textField = [alertView textFieldAtIndex:0];
textField.keyboardType = UIKeyboardTypeNumberPad;
[self performSelectorOnMainThread:#selector(ProcessDeleteTransaction:) withObject:textField.text waitUntilDone:NO];
}
break;
case 2:
[self.navigationController popToRootViewControllerAnimated:YES];
break;
default:
break;
}
}
Try this:
UIAlertView *a = [[UIAlertView alloc] initWithTitle:#"Howdie" message:#"msg" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
a.alertViewStyle = UIAlertViewStylePlainTextInput;
UITextField *textField = [a textFieldAtIndex:0];
assert(textField);
textField.keyboardType = UIKeyboardTypeNumberPad;
[a show];
I'm not really sure why you're posting code for your UIAlertViewDelegate method. Why not configure the keyboard type when the UIAlertView is created?
I actually had never tried this before but had a minute to give it a shot, and this code works fine:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:#"Test" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
UITextField *textField = [alert textFieldAtIndex:0];
textField.keyboardType = UIKeyboardTypeNumberPad;
[alert show];
As you know, - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex is a delegate method called when the user clicks a button on an alert view, but the textField.keyboardType should be set before becomeFirstResponder..so you should set keyboardType property once [[UIAlertView alloc] init]
Try this:
- (void)willPresentAlertView:(UIAlertView *)alertView {
[[alertView textFieldAtIndex:0] setKeyboardType:UIKeyboardTypeDecimalPad];
[[alertView textFieldAtIndex:0] becomeFirstResponder];
}

Resources