Retrieving tapped button on UIAlertView - objective-c

I had this code running on my app, and now on iOS 6 it crashes my app:
// Another method
[NSThread detachNewThreadSelector:#selector(askServerForNFeID)
toTarget:self withObject:nil];
- (void)askServerForNFeID {
if ([response isEqualToString:#"XXXX"]) {
NSString *responseMessage = [NSString stringWithFormat:
NSLocalizedString(#"Autorizado o Uso da NFe\n para chave:\n%#", #""),
[invoiceInfo NFeID]];
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:NSLocalizedString(#"Sefaz respondeu:", #"")
message:responseMessage
delegate:self
cancelButtonTitle:NSLocalizedString(#"OK", #"")
otherButtonTitles:nil];
[alert show];
[alert release];
}
}
I have learned that calling the alert from a second thread causes the crash, and so I changed my code to call the alert from the main thread like this:
if ([response isEqualToString:#"XXXX"]) {
[self performSelectorOnMainThread:#selector(showAlertHelper:)
withObject:[[NSArray alloc] initWithObjects:
NSLocalizedString(#"Não posso seguir em frente", #""),
NSLocalizedString(#"Você usou .....", #""), #"Fechar", #"Comprar", nil]
waitUntilDone:YES];
Note I am parsing the title, message and buttons as a list to showAlertHelper...
-(void)showAlertHelper:(NSArray*)theArray{
if ([[theArray objectAtIndex:3] isEqualToString:#""]) {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:[theArray objectAtIndex:0]
message:[theArray objectAtIndex:1]
delegate:nil
cancelButtonTitle:[theArray objectAtIndex:2]
otherButtonTitles:nil];
[alertView show];
[alertView release];
}
else {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:[theArray objectAtIndex:0]
message:[theArray objectAtIndex:1]
delegate:nil
cancelButtonTitle:[theArray objectAtIndex:2]
otherButtonTitles:[theArray objectAtIndex:3], nil];
[alertView show];
[alertView release];
}
}
My problem now, is that I had this handler to catch the button that was tapped, and it doesn't work any more. It just isn't called:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if ([title isEqualToString:NSLocalizedString(#"Comprar", #"")]) {
// Do stuff to buy credits...
} else if ([title isEqualToString:NSLocalizedString(#"Fechar", #"")]) {
NSLog(#"Fechar was selected.");
}
else if ([title isEqualToString:NSLocalizedString(#"Criar conta", #"")]) {
// Do stuff to create an account...
}
}

The problem is that in your re-written method, you set the delegate to nil instead of self. As a result, the alertView:clickedButtonAtIndex: delegate method isn't called. Change your code to the following: by specifying self in the delegate: parameter:
-(void)showAlertHelper:(NSArray*)theArray{
if ([[theArray objectAtIndex:3] isEqualToString:#""]) {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:[theArray objectAtIndex:0]
message:[theArray objectAtIndex:1]
delegate:self
cancelButtonTitle:[theArray objectAtIndex:2]
otherButtonTitles:nil];
[alertView show];
[alertView release];
} else {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:[theArray objectAtIndex:0]
message:[theArray objectAtIndex:1]
delegate:self
cancelButtonTitle:[theArray objectAtIndex:2]
otherButtonTitles:[theArray objectAtIndex:3], nil];
[alertView show];
[alertView release];
}
}

You removed the delegate from the creation method of your UIAlertView
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:[theArray objectAtIndex:0]
message:[theArray objectAtIndex:1]
delegate:nil
cancelButtonTitle:[theArray objectAtIndex:2]
otherButtonTitles:[theArray objectAtIndex:3], nil];
should be
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:[theArray objectAtIndex:0]
message:[theArray objectAtIndex:1]
delegate:self
cancelButtonTitle:[theArray objectAtIndex:2]
otherButtonTitles:[theArray objectAtIndex:3], nil];

Related

UIAlertView with textField

I experiment at the moment with some alertViews. Now try to set an AlertView with two textField`s. When I click "done" it should show a Log.
At the moment, the code looks like that:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Titel" message:#"Message" delegate:self cancelButtonTitle:#"Done" otherButtonTitles:#"Cancel", nil];
The TextField should have placeholder. How do I set it up?
Try this: it should work:
UIAlertView *av = [[UIAlertView alloc] initWithTitle:#"Your_Title" message:#"Your_message" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil];
[av setAlertViewStyle:UIAlertViewStyleLoginAndPasswordInput];
// Alert style customization
[[av textFieldAtIndex:1] setSecureTextEntry:NO];
[[av textFieldAtIndex:0] setPlaceholder:#"First_Placeholder"];
[[av textFieldAtIndex:1] setPlaceholder:#"Second_Placeholder"];
[av show];
You can access the values of the text fields on the alertView:clickedButtonAtIndex: of UIAlertViewDelegate.
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
NSLog(#"1 %#", [alertView textFieldAtIndex:0].text);
NSLog(#"2 %#", [alertView textFieldAtIndex:1].text);
}

multiple alert view in one view controller (tag doesn't work)

I have read some methods using alert view .tag, but that doesn't work.
The first alert:
-(void)addNewTask
{
UIAlertView * alert1 = [[UIAlertView alloc] initWithTitle:#"New Task"
message:nil
delegate:self
cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK",nil];
alert1.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert1 show];
}
The Second Alert
-(void)changeTime:(int)value atRow:(int)p
{
TaskData *data = [tasks objectAtIndex:p];
NSLog([NSString stringWithFormat:#"%d %d",data.time,value]);
int time = data.time ;
time += value;
data.time = time;
NSLog([NSString stringWithFormat:#"%d %d",data.time,value]);
[self saveData:tasks];
[self.Taskview reloadData];
if(time>=5&&(data.leveljudge!=1))
{
UIAlertView *alert2 = [[UIAlertView alloc] initWithTitle:#"Congratulation!!!"
message:#"You have achieve Senior Level. "
delegate:nil
cancelButtonTitle:#"Cancel" otherButtonTitles:#"YES",nil];
data.leveljudge=1;
[alert2 show];
}
Delegate:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
NSString *name = [alertView buttonTitleAtIndex:buttonIndex];
if ([name isEqualToString:#"OK"])
{
UITextField *tf=[alertView textFieldAtIndex:0];
NSString *name = tf.text;
TaskData *newTask = [[TaskData alloc] init];
newTask.TaskName = name;
newTask.time = 0;
newTask.leveljudge=0;
[tasks addObject:newTask];
[self saveData:tasks];
[self.Taskview reloadData];
}
else if ([name isEqualToString:#"YES"]) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"http://d.blog.xuite.net/d/1/5/4/12103250/blog_1606564/txt/53796893/2.jpg"]];
}
}
The problem is the delegate only work for the first alert.
My app looks like: https://www.youtube.com/watch?v=WxlVKk0CTiQ
-(IBAction)flipAction:(id)sender
{
UIAlertView *alert=[[UIAlertView alloc] initWithTitle:#"This is My Button" message:#" Hi" delegate:self cancelButtonTitle:#"OK " otherButtonTitles:#"Cancel", nil];
alert.tag=1;
[alert show];
[alert release];
}
-(IBAction)flipAction123:(id)sender
{
UIAlertView *alert=[[UIAlertView alloc] initWithTitle:#"This is a flipAction123" message:#"this is message..." delegate:self cancelButtonTitle:#"OK " otherButtonTitles:#"Cancel", nil];
alert.tag=2;
[alert show];
[alert release];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex;
{
if (alertView.tag==1)
{
if (buttonIndex==0)
{
UIAlertView *alert=[[UIAlertView alloc] initWithTitle:#"This is another alert button" message:#"" delegate:nil cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil];
[alert show];
[alert release];
}
else
{
NSLog(#"paresh here..");
}
}
else if(alertView.tag==2)
{
UIAlertView *alert=[[UIAlertView alloc] initWithTitle:#"This is another alert alertView.tag ==2" message:#"" delegate:nil cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil];
[alert show];
[alert release];
}
}
For alert2, Delegate is not called because you have not set the delegate.
Try making the following changes.
Alert1
UIAlertView * alert1 = [[UIAlertView alloc] initWithTitle:#"New Task"
message:nil
delegate:self
cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK",nil];
alert1.alertViewStyle = UIAlertViewStylePlainTextInput;
alert1.tag = 101; //Add a Tag to the alert
[alert1 show];
Alert2
Alert 2 delegate is not set properly
UIAlertView *alert2 = [[UIAlertView alloc] initWithTitle:#"Congratulation!!!"
message:#"You have achieve Senior Level. "
delegate:self //Set your delegate
cancelButtonTitle:#"Cancel" otherButtonTitles:#"YES",nil];
alert2.tag = 102; //Add a different tag value to the second alert
data.leveljudge=1;
[alert2 show];
Delegate
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(alertView.tag == 101)
{
//Handle Alert 1
}
else if(alertView.tag ==102)
{
//Handle Alert 2
}
}
UIAlertView *alert2 = [[UIAlertView alloc] initWithTitle:#"Congratulation!!!"
message:#"You have achieve Senior Level. "
delegate:self //here should be self, not nil
cancelButtonTitle:#"Cancel" otherButtonTitles:#"YES",nil];
data.leveljudge=1;
[alert2 show];

UIAlertView is causing a EXC_BAD_ACCESS and app hang

Ive the following code which is working fine , but when I add UIAlertView its start giving me exc_bad_access and the app hanged ,
The main idea is to show alert when timestamp dedtected ,
any tips what im doing wrong ?
- (void) onPayload:(PayloadEvent *) event {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *header = #"[OnPayload] ";
if (event.payloadType == TYPE_IDENTIFIED) {
if ((event.contentID != -1) && (event.timeStamp == -1)) {
[mUI performSelectorOnMainThread: #selector(Trace:) withObject:[NSString stringWithFormat:#"%# StaticID detected: %x\t\tConfidence: %f\n", header,(int)event.contentID, event.confidence] waitUntilDone:NO];
}
if ((event.timeStamp != -1) && (event.contentID == -1)) {
[mUI performSelectorOnMainThread: #selector(Trace:) withObject:[NSString stringWithFormat:#"%# Timestamp detected: %f\t\tConfidence: %f\n", header, event.timeStamp, event.confidence] waitUntilDone:NO];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Poll" message:#"MY alert Poll" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
[alert release];
}
}
else if (event.payloadType == TYPE_NOT_IDENTIFIED) {
[mUI performSelectorOnMainThread: #selector(Trace:) withObject:[NSString stringWithFormat:#"%# Content not marked\n", header] waitUntilDone:NO];
}
else if (event.payloadType == TYPE_MARKED_BUT_NOT_IDENTIFIED) {
[mUI performSelectorOnMainThread: #selector(Trace:) withObject:[NSString stringWithFormat:#"%# Content marked but not identified\n", header] waitUntilDone:NO];
}
[event release];
[pool release];
}
My error appear here
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Poll" message:#"MY alert Poll" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show]; <<=====
[alert release];
Any code that changes the UI should be called from the main thread:
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Poll" message:#"MY alert Poll" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
[alert release];
});
On the contrary to some comments, the view that is displaying the alert will retain the UIAlertView instance, so there is no need to call autorelease instead of release.
Considering that you are calling -performSelectorOnMainThread a few times in the same method, I imagine it's being called on a background thread. UI changes must occur on the main thread, and thus, you should be calling [alert show]; on the main thread in order to bypass the error.
[alert performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:NO];

Objective C dismissViewControllerAnimated move last view down

I have two ViewController
VC1 adding VC2 as an subview to itselfe.
VC2 has a UIButton, which is calling the follow Code:
if([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
mailer.mailComposeDelegate = self;
[mailer setSubject:[NSString stringWithFormat:#"BlaBla."]];
NSArray *toRecipients = [NSArray arrayWithObjects:#"blabla#gmail.com", nil];
[mailer setToRecipients:toRecipients];
NSString *emailBody = [NSString stringWithFormat:#"Testtext1"];
[mailer setMessageBody:emailBody isHTML:NO];
[self presentViewController:mailer animated:YES completion:nil];
}
else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Fehler" message:#"Ihr Gerät unterstützt die gewünschte Funktion nicht" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
}
After the Mail is done it calls the following:
-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error{
switch (result)
{
case MFMailComposeResultCancelled:
{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Hinweis"
message:#"Vorgang abgebrochen, es wurde keine E-Mail versendet."
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles: nil];
[alert show];
}
break;
case MFMailComposeResultSaved:
{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Hinweis"
message:#"Ihre E-Mail wurde gespeichert."
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles: nil];
[alert show];
}
break;
case MFMailComposeResultSent:
{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Hinweis"
message:#"Ihre E-Mail wird versendet."
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles: nil];
[alert show];
}
break;
case MFMailComposeResultFailed:
{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Hinweis"
message:#"Vorgang abgebrochen, die E-Mail konnte nicht gesendet werden."
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles: nil];
[alert show];
}
break;
default:
{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Hinweis"
message:#"E-Mail wurde nicht gesendet."
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles: nil];
[alert show];
}
break;
}
[self dismissViewControllerAnimated:YES completion:nil];}
All works fine, but all UIButtons etc in VC2 are now moved, I guess, 20 pixels down.
I cant Imagin why, I guess the problem is I adding a ViewController as Subview to an other ViewController and calling there the methode. But I cant imagin how to solve the issue.
I had similar problem but parent view was moved 20 px up.
Solution was based on changing "Wants full screen". I had to set this values to YES but not to all child view controllers.

Textfield resignFirstResponder Very late?

I have one strange problem.I have two UItextfields in my view and a button.When i click on button.I have changed the frame of view in animation block but it's resigning later here is my code if someone told me about this i'll be thankful
-(IBAction)SignINClicked
{
[Email resignFirstResponder]; //TextField
[Password resignFirstResponder];//TextField
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.10];
[[self view] setFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
[UIView commitAnimations];
sleep(0.10);
if([Email.text isEqualToString:#""] || [Password.text isEqualToString:#""])
{
if([Email.text isEqualToString:#""] && [Password.text isEqualToString:#""])
{
UIAlertView *Error = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Please fill email and password" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[Error show];
[Error release];
}
else if([Email.text isEqualToString:#""])
{
UIAlertView *Error = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Please fill email" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[Error show];
[Error release];
}
else if([Password.text isEqualToString:#""])
{
UIAlertView *Error = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Please fill password" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[Error show];
[Error release];
}
}
else
{
[AppDelegate startLoading];
BOOL isCorrectUser=[self logIn:Email.text Password:Password.text];
if (isCorrectUser==TRUE)
{
if(checkboxSelected==1)
[self rememberMe:YES];
else
[self rememberMe:NO];
[self performSelector:#selector(ShowDashboard) withObject:nil afterDelay:5];
}
else
{
[AppDelegate endLoading];
UIAlertView *Error = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Either user name/password is incorrect" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[Error show];
[Error release];
}
}
}
-(void)startLoading
{
[UIApplication sharedApplication].networkActivityIndicatorVisible=YES;
if(MyWaitViewObj==nil)
{
MyWaitViewObj = [[MyWaitViewController alloc] initWithNibName:#"MyWaitView" bundle:nil];
}
[NSThread detachNewThreadSelector:#selector(showMyWaitView) toTarget:self withObject:nil];
[NSThread sleepForTimeInterval:0.1];
}
-(void)endLoading
{
[MyWaitViewObj.view removeFromSuperview];
[UIApplication sharedApplication].networkActivityIndicatorVisible=NO;
}
Now when i click on signin button the [appdelegate startloading] method executes first and then keyboard hides.While actually it should hide the keyboard first and then start loading
Try taking out the sleep statement. If you need something to happen after a delay, put it in it's own method and call it with:
[self performSelector:#selector(someMethod:) withObject:nil afterDelay:someTimeDelay];