I have the following code that is called when my "gameover scene" appear for the 3rd time:
_alert = [[UIAlertView alloc] initWithTitle:#"Congratulations!!!\n\n"
"bla bla vla!"
message:NULL
delegate:nil
cancelButtonTitle:#"No, thanks"
otherButtonTitles:#"Rate",#"Later",nil];
if (![settings boolForKey:#"ShouldNotRateLater"]) {
[_alert show];
}
It started crashing on iOs 7 and it didn't happen in iOs 5 or 6.
I have already tried:
//[_alert performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:YES]; or
/*dispatch_async(dispatch_get_main_queue(), ^{
[_alert show];
[_alert release];
}); */
Those are tips I saw in other threads but it doesn't work for me.
Also, running the NSZombie I got the following log:
[UIImage isKindOfClass:]: message sent to deallocated instance 0x16da1dd0
Does any one know what I am doing wrong?
Many Thanks
set #property as strong instead of weak
#property(nonatomic,strong) UIAlertView *alert;
I tried your code like this and it works:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Congratulations!!!\n\n"
"bla bla vla!"
message:NULL
delegate:nil
cancelButtonTitle:#"No, thanks"
otherButtonTitles:#"Rate",#"Later",nil];
[alert show];
So either your _alert is declared the wrong way (weak vs. strong as #Ramshad suggests) or there is something wrong with your ![settings boolForKey:#"ShouldNotRateLater"]
Please post the error that you get.
Why are you using "NULL" for the message argument? The method is expecting and object pointer so the correct way is to use "nil" if you do not want any message.
Maybe that is the cause of your problem.
Related
I have a code in a class method that must show a UIAlertView on successful operation (it's a Facebook SDK handler).
But, the alert doesn't show up.
Here's the code:
-(void) postCompletionHandler:(FBRequestConnection *)connection
result:(id)
result error:(NSError*)error
{
if (!error) {
// Link posted successfully to Facebook
NSLog(#"result: %#", result);
UIAlertView *successAlert = [[UIAlertView alloc]
initWithTitle:#"FB Success!"
message:result
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[successAlert show];
}
}
I put a breakpoint inside the block and
[successAlert show];
reaches execution and successfully executes. The debugger also shows, that this code excuted from the main, GUI thread.
I can't even imagine what can be the problem here.
Any ideas?
Update: big thanks for everyone who participated, your help means so much for me.
Now I solved the problem. The problem was, as pointed by #rmaddy, in incorrect parameter result, given to a constructor of an alertView class.
In the future I'll investigate on exception handling techniques in Xcode to prevent such an obvious errors to ruin my code.
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Order"
message:#"Order Successfully Discontinued."
delegate:self
cancelButtonTitle:nil
otherButtonTitles: #"Ok",nil];
//[alertView performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:YES];
alertView.tag=TAG_DEV;
[alertView show];
-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
if(alertView.tag==TAG_DEV)
{
if(buttonIndex==0)
{
}
else
NSLog(#"Here");
}
}
This crashes. How can I fix it?
When you crash on a "objc_msgSend()" you are most likely sending a messageto an already-freed object. Or you have a pointer, which is correct, but something have changed the objects contents. Another cause can be the use of a dangling pointer that once pointed to the memory now occupied by your object. Occasionally objc_msgSend crashes because a memory error changed the runtime's own data structures, which then would cause trouble in the receiver object itself.
In this situation you need to check wheter or not, the delegate of the UIAlertview has been released after presenting, so when the alert is dismissed, it is not sending a message to it's delegate, which may be nil. An other option is that the UIViewController that presents the alert view is released after it is presented. Please check if the alert delegate is not released after it is presented.
This is my code
audioViewController *voiceRecorder = [audioViewController sharedManager];
[voiceRecorder stopRecording];
NSString *msg = [NSString stringWithFormat:#"Want to logout?"];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Info"
message:msg
delegate:self
cancelButtonTitle:#"No"
otherButtonTitles:#"Yes", nil];
alert.tag = 100;
[alert show];
I am calling sharedManager in one of my view controller. The problem is, my alertview runs before sharedManager method executes, if you check my code, i have called "StopReording" method, but when i run the code, it works after showing alert. Anyone has idea, how do I show alert only after the method returns something.?
You seem to be confusing yourself about method run order and alert presentation order. The methods run in the order specified by your code, they must. What you see on screen is 2 alerts, one (stop) presented first, the the other (logout) presented immediately after.
Generally, you shouldn't show 2 alerts at the same time. Certainly not if they relate to different things.
Present your first alert, then wait for the answer to be received (using the delegate methods). Once you have the users answer, then decide what to do next and present the second alert or continue with some other operation.
Followup to Where is NSAlert.h in the iOS SDK?
Is there any way to get NSAlert runModal like behavior from a UIAlertView? Or from a UIActionSheet?
I'm planning on using only in debug builds so I'm not concerned with how it looks or if it uses undocumented functionality.
Edit:
NSAlert is part of the OS X SDK and is similar to MessageBox in Win32. It allows you to synchronously prompt the user for something. Here's an example:
NSAlert * myAlert=[[NSAlert alloc] init];
[myAlert setMessgeText:#"This is my alert"];
[myAlert addButtonWithTitle:#"button 1"];
[myAlert addButtonWithTitle:#"button 2"];
switch ([myAlert runModal]) {
case NSAlertFirstButtonReturn:
//handle first button
break;
case NSAlertSecondButtonReturn:
//handle second button
break;
}
runModal is a synchronous function, it shows the alert and waits for user response. Internally it is running a limited version of the message loop, but as far as the rest of my application is concerned, the world has stopped; no messages, no events, nothing.
Internally it is running a limited version of the message loop, but as far as the rest of my application is concerned, the world has stopped
Just do exactly what you described: throw up the alert, then run the event loop till the alert view gets dismissed. This code works:
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"O rlly?" message:nil delegate:nil
cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[alert show];
NSRunLoop *rl = [NSRunLoop currentRunLoop];
NSDate *d;
while ([alert isVisible]) {
d = [[NSDate alloc] init];
[rl runUntilDate:d];
[d release];
}
[alert release];
You'll have to write your own if you want this behavior. Careful, if you block the main queue for too long, your app will be watchdog'd.
UIAlertView gives you modal behavior, and will end up working the same way your custom class will. You might consider using a block-based wrapper that wraps up UIAlertView and allows you to setup blocks for the button action callbacks.
I have a simple application which was working fine until I added some code which launches a new thread at some point and then tries to show an alert from that thread. Now, the app crashes whenever the code for showing the alert is hit.
UIAlertView * addAlert = [[UIAlertView alloc] initWithTitle:#"New alert"
message:#"Example alert"
delegate:nil
cancelButtonTitle:#"Cancel", otherButtonTitles:#"OK", nil];
[addAlert show];
[addAlert release];
My question is: is it possible to display UI elements such as alerts from multiple threads on iOS?
You definitely don't want to be displaying an alert (or anything UI-related) from any thread other than the main thread. I'd suggest putting your alert code in a function and call one of the performSelectorOnMainThread calls.
- (void) showAlert
{
UIAlertView * addAlert = [[UIAlertView alloc] initWithTitle:#"New alert"
message:#"Example alert"
delegate:nil
cancelButtonTitle:#"Cancel", otherButtonTitles:#"OK", nil];
[addAlert show];
[addAlert release];
}
// ... somewhere in the worker thread ...
[self performSelectorOnMainThread:#selector(showAlert) withObject:nil waitUntilDone:NO];
I'm pretty sure that the main thread is the only thread that should be the one that handles UI recognition/drawing things to screen. What I would do if I were in your position would to be either use KVO notifications or implement a protocol that some class subscribes to. Going the protocol route, when you get to the alerting part of your code merely have that thread call its protocol method, the subscribing class will be alerted by having the delegate function triggered and you can easily present whatever you have to in that view via the main thread.
Hope that helps.
Better and simple and just one line approach is to call performSelectorOnMainThread method with alertView.
In your case try this line
[addAlert performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:YES];
instead of
[addAlert show];
It will call show method of Alertview on main thread. No need to write any extra method.