NSException thrown on uialert - objective-c

I have an ios app that throws an alert when an error code is given.
the code is this.
NSString *errorMessage = [[json valueForKey:#"message"] stringByRemovingPercentEncoding];
if(errorMessage == nil)
errorMessage = [NSString stringWithFormat:#"Error Code : %#", [json valueForKey:#"code"]];
UIAlertController *alertView = [UIAlertController alertControllerWithTitle:errorMessage message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *yesButton = [UIAlertAction actionWithTitle:#"확인" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[alertView dismissViewControllerAnimated:YES completion:nil];
}];
[alertView addAction:yesButton];
[self presentViewController:alertView animated:YES completion:nil];
return nil;
But it keeps giving me
2020-04-23 17:06:49.247744+0900 timekeeper[64197:20858252] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.'
* First throw call stack:
(0x19e8f496c 0x19e60d028 0x19ede05e0 0x19ebcf828 0x1a2dce250 0x1a2dcf648 0x1a2027d74 0x1a20234b8 0x1a202372c 0x1a2023a6c 0x1a2028630 0x1a2028474 0x1a2009364 0x1a23b0a1c 0x1a23b1104 0x1a23c7214 0x1a23bfd08 0x1a23c175c 0x1a23c3d0c 0x1a23c4270 0x1a23c3c58 0x1a23c3eec 0x1023b2924 0x1023b1028 0x19ebadfa4 0x19ece9a74 0x19e5fd840 0x19e6059f4)
libc++abi.dylib: terminating with uncaught exception of type NSException
error
what is the problem?? It worked fine few days ago.

You need to present the UIAlertController in the main thread.
Something like this:
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:alertView animated:YES completion:nil];
});
Hope this helps

Related

App crashes when mail account is not setup

App is randomly crashing when mail account is not setup. Sometimes, I am getting error alert. Please help me.
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
mc.mailComposeDelegate = self;
[mc addAttachmentData:myData mimeType:#"application/pdf" fileName:#"myPdf2.pdf"];
[self presentViewController:mc animated:YES completion:NULL];
}
else {
UIAlertController * alert = [UIAlertController
alertControllerWithTitle:#"Alert"
message:#"Please set up your mail account!"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* okButton = [UIAlertAction
actionWithTitle:#"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
//Handle your yes please button action here
}];
[alert addAction:okButton];
[self presentViewController:alert animated:YES completion:nil];
}

MFMailComposer Dismissing immediately after launch

I am trying to launch the MFMailComposer on the iOS 7 simulator and as soon as it comes up it immediately dissmises itself and I get the following error in the debugger.
_serviceViewControllerReady:error: Error Domain=NSCocoaErrorDomain Code=4097 "The operation couldn’t be completed. (Cocoa error 4097.)"
Here is my code
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
switch (buttonIndex) {
case 0:
break;
case 1:{
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mailViewController = [[MFMailComposeViewController alloc] init];
mailViewController.mailComposeDelegate = self;
[mailViewController setSubject:[NSString stringWithFormat:#"%# Totals Report",_teamStats.relationshipTeam.teamName]];
[mailViewController setMessageBody:#"\n\n\n\n\nSent From HoopMetrics" isHTML:NO];
// Attach a doc to the email
NSData* data = [_teamStats.relationshipTeam pdfDataFromString:_teamStats.teamTotalsAsString];
[mailViewController addAttachmentData:data mimeType:#"application/pdf" fileName:#"Totals Report"];
[self presentViewController:mailViewController animated:YES completion:nil];
}
else{
HMAlertView*alert = [[HMAlertView alloc]initWithTitle:#"No Email" message:#"Please, set up an email account on your device" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
}
break;
}
I faced the same problem. Just turn off appearance customization for UINavigationBar or UIBarButtonItem or some another element that MFMailComposeViewController may use.
You can get around this with the following hack using performSelector:
- (IBAction)sendEmail:(id)sender {
[self performSelector:#selector(showEmailComposer) withObject:nil afterDelay:0.0];
}
-(void) showEmailComposer{
MFMailComposeViewController *mailViewController = [[MFMailComposeViewController alloc] init];
//Set recipients...other stuff
[mailViewController setToRecipients:recipients];
[mailViewController setSubject:subject];
[mailViewController setMessageBody:body isHTML:isHTML];
mailViewController.title = #"Email VC Title";
mailViewController.mailComposeDelegate = delegate;
[self presentViewController:mailViewController
animated:YES
completion:NULL];
}

UIAlertView makes the program crash

I've got a crash:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UIKeyboardTaskQueue performTask:] may only be called from the main thread.'
And I could not find a solution for 2 days.
And here is the code:
[alert dismissWithClickedButtonIndex:0 animated:YES];
UIAlertView *noTicketAlert = [[UIAlertView alloc] initWithTitle:#"Aradığınız kriterlere uygun bilet bulunamadı!" message:nil delegate:self cancelButtonTitle:#"Tamam" otherButtonTitles: nil];
[noTicketAlert show];
I triggered this error by attempting to display an alert from a background thread. Fixed like this:
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:...
[alertView show];
});
I got this error when presenting a UIAlertView normally (no funny button override stuff). It turned out that I was presenting it twice in quick succession. The fix in my case was to remove the erroneous duplicate call.
If you do need to present two alert views at close to the same time, and you get this error, then a fix that works (and addresses the error message itself) is to run the code on the main thread:
[[NSOperationQueue mainQueue] addOperationWithBlock:^
{
// Your code that presents the alert view(s)
}];
Yes, I've found the solution and I share that with you guys.
I tried to override the dismissWithClickedButtonIndex function, and sent unique buttonIndexes
like 9999 for each of my alerts.
That is,
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
[self viewWillDisappear:YES];
if(buttonIndex == 9999) {
noTicketAlert = [[UIAlertView alloc] initWithTitle:#"Aradığınız kriterlere uygun bilet bulunamadı!" message:nil delegate:self cancelButtonTitle:#"Tamam" otherButtonTitles: nil];
[noTicketAlert show];
}
}
and if I want to display the noticketAlert, I call this method like :
[alert dismissWithClickedButtonIndex:9999 animated:YES];
If you have a custom button make sure you implement the delegate method:
- (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
{
return YES;
}
if this selector is not found then the program with crash..
For those looking for the Swift 2 answer to this issue, I ran into a similar problem and solved it with #Dave Batton's solution
dispatch_async(dispatch_get_main_queue(), {
self.performSegueWithIdentifier("loginSegue", sender: self)
})

UIAlertView button results in a child NSThread

I would like a user to get a prompt screen, it would have yes and no options.
The problem is the UIAlertView cannot be called from child thread, if I call it from child thread I am getting a runtime error(EXC_BAD_ACCESS). I am using NSThread on IOS6.1
This is the code that i am using
-(void) construct
{
NSThread *initThread =[[NSThread alloc]initWithTarget:self selector:#selector(error) object:nil];
[initThread start];
}
- (void) error
{
//make sure it runs on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Save"
message:#"Enter File Name"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil];
alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
[alertView show];
});
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
NSLog(#"Alert View dismissed with button at index %d",buttonIndex);
switch (alertView.alertViewStyle)
{
case UIAlertViewStylePlainTextInput:
{
UITextField *textField = [alertView textFieldAtIndex:0];
NSLog(#"Plain text input: %#",textField.text);
} break;
case UIAlertViewStyleSecureTextInput:
{
UITextField *textField = [alertView textFieldAtIndex:0];
NSLog(#"Secure text input: %#",textField.text);
} break;
case UIAlertViewStyleLoginAndPasswordInput:
{
UITextField *loginField = [alertView textFieldAtIndex:0];
NSLog(#"Login input: %#",loginField.text);
UITextField *passwordField = [alertView textFieldAtIndex:1];
NSLog(#"Password input: %#",passwordField.text);
}break;
default: break;
}
}
This is the error that I am getting:
[NSURLCacheInternal alertView:didDismissWithButtonIndex:]: unrecognized selector sent to instance 0x8653630
2013-07-26 16:12:35.738 iOSTrack[7455:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSURLCacheInternal alertView:didDismissWithButtonIndex:]: unrecognized selector sent to instance 0x8653630'
*** First throw call stack:
(0x1e7a012 0x1796e7e 0x1f054bd 0x1e69bbc 0x1e6994e 0x7c0e13 0x408d66 0x408f04 0x20e7d8 0x266b014 0x265b7d5 0x1e20af5 0x1e1ff44 0x1e1fe1b 0x1dd47e3 0x1dd4668 0x3caffc 0x21cd 0x20f5)
libc++abi.dylib: terminate called throwing an exception
Most likely what is happening is that your UIAlertView is a local variable and it's getting destroyed before the delegate has a chance to run. You need to keep a reference to it around long enough such that your delegate has a chance to run and do it's work. Then you are in the clear. This concept applies to both ARC and manual memory managed based code.
See this related question: UIAlertViewDelegate class "self" instance gets dealloc'd before button gets pressed
The code I tried actually worked fine for me
The only difference is
[alertView show] => [alertView show]; you miss ;,a typo in question i guess
running the code in seperate thread
dispatch_queue_t myQueue = dispatch_queue_create("My Queue",NULL);
dispatch_async(myQueue, ^{
// Perform long running process
[self error];
});
- (void) error {
//make sure it runs on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Save"
message:#"Enter File Name"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil];
alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
[alertView show];
});
}

Getting a SIGABRT error in dismissModalViewController

Im receiving a SIGABRT error when I cancel a MFMailComposeViewController, exactly in the dismissViewController, don't work
I have a UIViewController within a UINavigationController.
My Code:
- (void)sendMail {
if ([MFMailComposeViewController canSendMail]) {
controller = [[MFMailComposeViewController alloc] init];
[[controller navigationBar] setTintColor:[UIColor getHexColorWithRGB:#"e2de09" alpha:1.0f]];
controller.mailComposeDelegate = self;
[controller setSubject:#"Subject"];
NSString *msg="xxxxx";
[controller setMessageBody:msg isHTML:YES];
[self presentModalViewController:controller animated:YES];
} else {
NSString * errorString = [NSString stringWithFormat:#"mail account not set."];
UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:#"Error:" message:errorString delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
}
The presentModalViewController:animated: works correctly.
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
[self becomeFirstResponder];
[self dismissModalViewControllerAnimated:YES];
}
But calling [self dissmissModalViewControllerAnimatedLYES] causes a SIGABRT error.
I think the "dismissModalViewControllerAnimated" should be called on the MFMailComposer object, in your case "controller". Note that it is in fact a view controller.
It's resolved!
I had a viewWillDisappear: method where I was removing views...
This method was being called before of present the ModalView and my ViewController was over released on dissmissModalViewController.
I have changed this method.
Thanks