UIAlertView didmissWithClickedButtonIndex does not dismiss the alert - iphone

From my object that handles the web service connection, when the network fails, I pass an alert to the view controller that uses the web service object.
WebServiceObject:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:[NSString stringWithFormat:#"Connection failed! You must be connected to a Wifi source to download data. Please reconnect to a Wifi source and try again later."] delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles: nil];
NSDictionary *alertDict = [NSDictionary dictionaryWithObjectsAndKeys:alert, #"AlertView", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:DisplayAlertNotification object:self userInfo:alertDict];
ViewController:
- (void)displayAlert:(NSNotification *)notification {
NSDictionary *dict = [notification userInfo];
if ([[dict objectForKey:#"AlertView"] isKindOfClass:[UIAlertView class]]) {
UIAlertView *alert = [dict objectForKey:#"AlertView"];
NSNumber *theTag = [dict objectForKey:#"AlertTag"];
NSLog(#"%i", [theTag integerValue]);
alert.tag = [[dict objectForKey:#"AlertTag"] integerValue];
[alert show];
}
}
- (void)removeAlert:(NSNotification *)notification {
NSDictionary *dict = [notification userInfo];
if ([[dict objectForKey:#"AlertTag"] isKindOfClass:[NSNumber class]]) {
NSNumber *theTag = [dict objectForKey:#"AlertTag"];
UIAlertView *alert = (UIAlertView *)[self.view viewWithTag:[theTag integerValue]];
// Not sure why but my alert is nil at this point
[alert dismissWithClickedButtonIndex:0 animated:YES];
}
}
I also use the removeAlert method in the same way to remove the alert programmatically. The goal of this is so if the network failed, but the user didn't click Ok yet, and then the network came back on, I would dismiss the Network Failed alert, and show the Network Resumed alert. It works except after it dismisses the alert and shows the Network Resumed, once the user clicks Ok on the Network Resumed, the original Network Failed comes back up just once. If the user clicked Ok while the Network Failed was presented, it never comes back up.
Am I dismissing the alert correctly this way? Thanks.
Edit: I can get it to work by just saving a reference in the WebServiceObject and dismissing it that way.

you set the alert to nil, so it do nothing
alert = nil;
[alert dismissWithClickedButtonIndex:0 animated:YES];

Related

how to call a storyboard scene conditionally from a button

I have an application who's first scene is a login screen. On pressing the login button, if the username and password are correct, the next scene should get called. Otherwise an alert is shown. But I am unable to figure out how to get the next scene conditionally.
if ([jsonDict valueForKey:#"success"] && [jsonDict valueForKey:#"redirect"]) {
NSLog(#"%#", [jsonDict valueForKey:#"success"]);
NSLog(#"%#", [jsonDict valueForKey:#"redirect"]);
NSString *redirect = [jsonDict valueForKey:#"redirect"];
[self performSegueWithIdentifier:#"next" sender:self];
}
else {
NSArray *jsonArray = [jsonDict valueForKey:#"errors"];
NSString *err = [jsonArray objectAtIndex:0];
NSLog(#"%#", err);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Invalid Credentials!" message:err delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
}
Set up a Segue to the next viewcontroller in your storyboard and give that segue a unique identifier. Then, if username and password are ok, just call
[self performSegueWithIdentifier:#"yourSegueIdentifier" sender:self];
Use below code:
- (void)validateLogin{
//code to check username and password are correct
if(correct){
[self performSegueWithIdentifier:#"SignInToNextScreen" sender:self];
}else{
UIAlertView *myalert = [[UIAlertView alloc]initWithTitle:#"Login Failed" message:#"Invalid Username/Password" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
}
}
//SignInToNextScreen is a segue identifier for manually triggered segue.
Please see the attached screen shot

Button not showing in nslocalnotification?

I have written the following code for displaying local notifications.However,a button is not showing up on the notifications when i receive them.Can anybody tell me what I am doing wrong?
I have written the following piece of code in application did enter background event.
UILocalNotification *local=[[UILocalNotification alloc]init];
NSDate *alertTime = [[NSDate date] dateByAddingTimeInterval:10];
local.fireDate=alertTime;
local.timeZone=[NSTimeZone defaultTimeZone];
local.alertBody=#"Hello this is a local notif";
local.alertAction=#"Show";
local.repeatInterval=0;
local.applicationIconBadgeNumber=1;
local.soundName=UILocalNotificationDefaultSoundName;
UIApplication *abc=[UIApplication sharedApplication];
[abc scheduleLocalNotification:local];
You have to write your code in AppDelegate.m File in below method.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
if (application.applicationState == UIApplicationStateActive) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:notification.alertBody delegate:nil cancelButtonTitle:nil otherButtonTitles:#"Show", nil];
[alert show];
[alert release];
}
}

UIAlertView on main queue crashing.

I have an issue showing a UIAlertView on the main thread. I'm not sure why but it keeps crashing, despite me running on the main thread. The following block is on the background thread, but I have the alert on the main as below:
void (^removeFromCalendar)(NSString *, NSString *, EKEventStore *) = ^(NSString *error, NSString *eventKey, EKEventStore *eventDB) {
EKEvent *myEvent = [eventDB eventWithIdentifier:eventKey];
NSError *err = noErr;
if(myEvent != NULL && myEvent != (id)[NSNull null]) {
[eventDB removeEvent:myEvent span:EKSpanThisEvent error:&err];
} else {
// Event was not found, nothing to do
return;
}
[eventDB release];
if (!err || err == noErr) {
NSLog(#"Deleted event %#", myEvent.title);
// Show alert on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
// Showing the alert for unattending
NSString *resultString = #"This event was removed from your calendar.";
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:#"Info" message:resultString delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil] autorelease];
[alert show];
});
return;
}
error = err.description;
};
If I comment out the bottom where it shows the alert, everything is fine. But for the alert, I keep getting a EXC_BAD_ACCESS error. Can somebody explain why? It's on the correct thread, and I cant for the life of me understand where the memory issue could come from!
May be you view is being released when you finish until you finish with the background queue. So, for safety why dont you use it like this;
...........
UIViewController __weak *myController = self;
dispathch_async(backgroundQueue, ^{
UIViewController __strong *myStrongController = myController;
...............
dispatch_async(dispatch_get_main_queue(), ^{
if(myStrongController){
// Showing the alert for unattending
NSString *resultString = #"This event was removed from your calendar.";
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:#"Info" message:resultString delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil] autorelease];
[alert show];
}
});
}).
This is how you present an alert view:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"<#(NSString *)#>" message:#"<#(NSString *)#>" delegate:self cancelButtonTitle:#"<#(NSString *)#>" otherButtonTitles:nil];
[alert show];
[alert release];
Instead of using dispatch_async, why not use the objective C call:
[self performSelectorOnMainThread
You might have to package it up in its own method. Alternatively, call it using:
[self performSelector:#selector(myAlertMethod) withObject:nil afterDelay:0.25]
These methods have been tried and true since day 1.

Unable to show UIAlertView

in my app i am using validation keys to download content from a server using Wi-Fi. I need to show a UIAlert if the licence keys are wrong or if the wi-fi is not available. I have written the coed for displaying the alert view but the alert is not being displayed... This is scking the blood out my head... Can anyone help please....the control is going over this line, but still the alert is not being displayed.
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *documentsDirectory= [[[UIApplication sharedApplication] delegate] applicationDocumentsDirectory]; //[pathToStore objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingFormat:#"packages"];
NSString *packagePath = [NSString stringWithFormat:#"%#/%#", path,isbnTemp];
[recievedData writeToFile:[documentsDirectory stringByAppendingPathComponent:#"file.zip"] atomically:YES];
NSString *zipPath=[documentsDirectory stringByAppendingPathComponent:#"file.zip"];
[fileManager createDirectoryAtPath:documentsDirectory withIntermediateDirectories:NO attributes:nil error:nil];
ZipArchive *zipArchive = [[ZipArchive alloc]init];
if([zipArchive UnzipOpenFile:zipPath]){
if([zipArchive UnzipFileTo:packagePath overWrite:YES]){
[self loadContent];
}
else{
NSLog(#"Unable to UnArchieve the packages");
}
}
else {
NSLog(#"Failure To Open Archive");
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"Your ISBN and/or Licence Key are incorrect" message:Nil delegate:self cancelButtonTitle:#"ok" otherButtonTitles:nil];
[alert show];
[alert release];
}
}
Are you trying to show the UIAlertView in a method that is being called from a thread other than the main thread? For example, if you are trying to show the UIAlertView in an asynchronous callback, it could be running on a separate thread.
If so, you need to move the code that shows the UIAlertView to a separate selector, and call it on the main thread using one of the performSelectorOnMainThread: methods.
For example, add the following method to your class:
-(void)showAlert {
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"Your ISBN and/or Licence Key are incorrect" message:Nil delegate:self cancelButtonTitle:#"ok" otherButtonTitles:nil];
[alert show];
[alert release];
}
And then change the last else clause in your current code so that it uses:
[self performSelectorOnMainThread:#selector(showAlert) withObject:nil waitUntilDone:NO];
See the NSObject class reference for more information on the performSelectorOnMainThread: methods.
After you've created the alert could you check for a NULL pointer in the alert variable?
Maybe you need to specify a message? Other than that I can't see anything wrong with the code you've posted.

External accessory notification:

I am developing an application, it gets data from accessory via UART port. I am having a problem when my application runs for a long time, it uses much more memory, after the iPhone into sleep mode, and wake up again, my application can not open the session with accessory after the accessory has been authenticated completely. After I debug class EAAccessoryManager, I see two identical devices, they are all my accessory. Go to Settings / General / About, I found that iphone show two identical devices there.
But my problem occurs only on the iPhone 3G (version iOS 4.1), The iPhone 3GS (iOS 4.1) does not have this problem. I guess because my program uses too much memory so I can not get accessoryDidDisconnect events. Please give me some advices. thank for your answer.
-(EASession*) openSessionForProtocol: (NSString*)protocolString
{
NSArray* accessories = [[EAAccessoryManager sharedAccessoryManager] connectedAccessories];
EAAccessory* accessory = nil;
EASession *session = nil;
for(EAAccessory* obj in accessories){
if([[obj protocolStrings] containsObject:protocolString]){
accessory = obj;
break;
}
}
if(accessory){
[accessory setDelegate:self];
session = [[EASession alloc] initWithAccessory:accessory forProtocol:protocolString];
if(session){
NSString *msg = #"";
for(EAAccessory* obj in accessories){
msg = [msg stringByAppendingFormat:#"\n%#",[obj name]];
}
NSString *openSession = [NSString stringWithFormat:#"The number of devices is: %d.%#",[accessories count],msg];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"OpenSession" message:openSession delegate:nil cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
[alert release];
[[session inputStream] setDelegate:self];
[[session inputStream] scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
[[session inputStream] open];
[[session outputStream] setDelegate:self];
[[session outputStream] scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
[[session outputStream] open];
[session autorelease];
iRemoteAppDelegate *appDelegate = (iRemoteAppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate SetApplicationRotation:TRUE];
}
}
return session;
}
- (void)accessoryDidDisconnect:(EAAccessory *)accessory
{
//[HardwareController performSelectorOnMainThread:#selector(UpdateStringOnMessage:) withObject:#"Can not connect hardware module.\nPlease check hardware again." waitUntilDone:YES];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Message" message:#"Accessory is unpluged!" delegate:nil cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
[alert release];
[[serialSession inputStream] removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
[[serialSession outputStream] removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
[serialSession release];
self.serialSession = nil;
iRemoteAppDelegate *delegate = (iRemoteAppDelegate *)[[UIApplication sharedApplication] delegate];
[delegate setUserCancel:NO];
AllowedEmitSignal = TRUE;
[delegate UpdateAboutHardwareDisconnect];
[delegate SetApplicationRotation:FALSE];
}
- (void)accessoryDidConnect:(NSNotification *) notification
{
iRemoteAppDelegate *appDelegate = (iRemoteAppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate setUserCancel:NO];
[self OpenPort];
AllowedEmitSignal = TRUE;
[appDelegate UpdateAboutHardwareDisconnect];
appDelegate.CallNumber = appDelegate.CallNumber+1;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Message" message:[NSString stringWithFormat:#"Accessory is attached!%d",appDelegate.CallNumber] delegate:nil cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
[alert release];
}
-(void)OpenPort
{
int i =0;
[self initAllVariable];
iRemoteAppDelegate *delegate = (iRemoteAppDelegate *)[[UIApplication sharedApplication] delegate];
for (;self.serialSession==nil && i<2; i++) {
self.serialSession = [self openSessionForProtocol:PROTOCOLSTRING];
}
}
If Settings / General / About shows two identical devices for iPhone 3G, this means the iPhone 3G has failed to detect the "the off" state of accessory when it sleeps. You have to ensure the accessory also went to sleep (low power state) when the iPhone 3G sleeps, within certain milliseconds after your accessory receives bytes from 3G telling it's changing its power state.
Cannot tell too much secret here. But from my experience, iPhone 3G has much difference electrical signal behavior with 3GS. Your problem has no relationship with iOS app code. I strongly suggest you to use CRO / Logic Analyzer to debug the detect pins state and commands sent from iPhone 3G just before it goes to sleep.