fire an alert when a UILocalNotification is called - iphone

I have a UILocalNotification and I want to fire an alert when the app recovers from background to foreground. I can create the alert in didReceiveLocalNotification, but this method can only be called when the app is active. Now I want to check if a notification was fired while the app is in background and then fire an alert when the app recovers.
this is my current method
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
application.applicationIconBadgeNumber = 0;
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSLog(#"prefs %#",[prefs stringForKey:#"kTimerNotificationUserDef"]);
if([prefs stringForKey:#"kTimerNotificationUserDef"] != nil)
{
[prefs setObject:nil forKey:#"kTimerNotificationUserDef"];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Timer Alert" message:[prefs stringForKey:#"kTimerNotificationUserDef"] delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
}
}
the NSUserDefaults is set when I initialize the notification, however, this alert is called even though the notification did not arrive yet. So, Im assuming maybe I can do something like:
if([prefs stringForKey:#"kTimerNotificationUserDef"] != nil && didFireNotifFromBackground)
any suggestions? thanks!

- (void)application:(UIApplication *)application
didReceiveLocalNotification:(UILocalNotification *)notification {
notification.applicationIconBadgeNumber = 0;
NSString *reminderText = [notification.userInfo objectForKey:kRemindMeNotificationDataKey];
[viewController showReminder:reminderText];
}
show the alertview where class u want to show
- (void)showReminder:(NSString *)text
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Reminder" message:text delegate:nil cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
[alertView release];
}

It is in your settings. Settings ->Notification->Your application in right side-> Choose your alert style.
Then you get alert directly while firing local notification

Related

Check if Notify Alert is Displayed - Bluetooth Notify On Disconnect

My iPhone app connects to a BLE Peripheral using this line of code:
[manager connectPeripheral:per.peripheral options:[NSDictionary dictionaryWithObject [NSNumber numberWithBool:YES]
forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
I enable the option to notify the user upon the peripheral disconnecting which will only happen when the app isn't being used (i.e. the iPhone is locked or the app is in the background)
When the peripheral disconnects, it calls a function in which I display an alert to the user telling them it disconnected:
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
//Show alert to the user
NSString *str = [[NSString alloc] initWithFormat:#"Peripheral disconnected. Try connecting again. Error: %#", error.localizedDescription];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Peripheral Disconnected"
message:str delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[self.navigationController popToRootViewControllerAnimated:NO];
}
The problem that I have is that when the iPhone is locked and the peripheral disconnects, both alerts pop up and it makes the user click "OK" on both alerts. How can I check to see if the "NotifyOnDisconnect" alert is being displayed to cancel showing the other alert?
You could avoid using CBConnectPeripheralOptionNotifyOnDisconnectionKey altogether and in your -centralManager:didDisconnectPeripheral: implementation, check if the app is in the background and present a UILocalNotification if it is in the background or your existing UIAlertView if the app is in the foreground. This way only one alert will be presented.

UIAlertView, once the user opens the app. Shown once

I want a UIAlertView to show, once the user opens the app. It'll ask them for their email address. But i want it to only show once. So when the user re opens the app the uialertview shouldnt pop up. And the UIAlertView will contain 2 buttons within that. 'Dismiss' & 'Yes' .. the dismiss button will continue with the app. But the 'Yes' will take them to another view'.
Thanks :)
Edit:
- (void)viewDidLoad {
[super viewDidLoad];
if (![#"1" isEqualToString:[[NSUserDefaults standardUserDefaults] objectForKey:#"alert"]]) {
[[NSUserDefaults standardUserDefaults] setValue:#"1" forKey:#"alert"];
[[NSUserDefaults standardUserDefaults] synchronize];
UIAlertView *prompt = [[UIAlertView alloc] initWithTitle:#"Enter your email"
message:#"\n\n\n"
delegate:nil
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Enter", nil];
textField = [[UITextField alloc] initWithFrame:CGRectMake(12.0, 50.0, 260.0, 25.0)];
[textField setBackgroundColor:[UIColor whiteColor]];
[textField setPlaceholder:#"enter email here"];
[prompt addSubview:textField];
[prompt show];
[prompt release];
//[textField becomeFirstResponder];
}
}
Okay this is the code at the moment, im stuck on how the email is going to be sent to be once the user presses enter.
You can use NSUserDefaults to save a boolean between sessions.
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/Reference/Reference.html
// save
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:true] forKey:#"hasRunBefore"];
// load
[[NSUserDefaults standardUserDefaults] objectForKey:#"hasRunBefore"] boolValue];
You could store the email address in NSUserDefaults (I guess you are already doing it, if you ask for it only the very first time your app starts); each time the app starts, you check if the email address is there (NSUserDefaults); if not, you display the UIAlertView.
First, need to make yourself the delegate for the UIAlertView so you know when the user has pressed Cancel or Enter. So this:
UIAlertView *prompt = [[UIAlertView alloc] initWithTitle:#"Enter your email"
message:#"\n\n\n"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Enter", nil];
The delegate callback is this method:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
Once that's called, you can retrieve the email address from the textField instance you created and added to the alert view.

One time UIAlert?

I want to do a UIalert the first time a user opens my app, to tell them about basic functionality, but I don't want it showing up every time they open the app or reload the home screen. I've seen this in other apps but don't know what the best way of going about it would be. If anyone could point me in the right direction on this it would be appreciated.
Stick this into you App Delegate in the - (void)applicationDidFinishLaunching:(UIApplication )application method
BOOL hasRunBefore = [[NSUserDefaults standardUserDefaults] boolForKey:#"FirstRun"];
if (!hasRunBefore) {
UIAlertView *firstRun = [[UIAlertView alloc] initWithTitle:#"Virgin" message:#"Hello World!!" delegate:nil cancelButtonTitle:#"Done" otherButtonTitles:nil];
[firstRun show];
[firstRun release];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"FirstRun"];
}
else if (hasRunBefore) {
//can do some else if run before
}
Basically what this does is check for the key "FirstRun" in NSUserDefaults, similarly this could be modified to be a version number or something, say if you wanted a new alert after each update or something. It then checks if the key does not else (!hasRunBefore) and if it does not exist (so never been run before) it creates a UIAlertView and then sets YES for the key (also creating that ket in process)
Use "[NSUserDefaults standardUserDefaults]" to write a boolean if they've started the app before or not.
I use NSUserDefaults in the viewDidLoad method of my main screen. So every time the app starts and the main screen loads, it checks if its the user's first time.
This is how I do it in my app:
- (void)viewDidLoad {
BOOL tempBOOL = [[NSUserDefaults standardUserDefaults] boolForKey:#"hasSeenOpeningAlert"];
if (!tempBOOL) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Welcome To My App" message:#"This app will ... First you need to ..." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
[alert release];
}
[super viewDidLoad];
}
and then:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
Edit *editViewController = [[[Edit alloc] initWithNibName:#"Edit" bundle:nil]retain];
[self.navigationController presentModalViewController:editViewController animated:YES];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"hasSeenOpeningAlert"];
[[NSUserDefaults standardUserDefaults] synchronize];
[editViewController release];
}

How to get a UIAlertView's result?

I implemented the gamekit. All works fine now. But if the user presses on send the data will instantly send to the other iphone/ipod/ipad and it will instantly written.
So now i wanted to implemenr a confirm screen for the receiver.
In my receiveData method (from the gamekit) i have an array. If the user presses yes the array will be written into a file.if not it wont be written into a file.
#pragma mark -
#pragma mark - GKreceiveData
- (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context
{
NSDictionary *dict = [NSKeyedUnarchiver unarchiveObjectWithData:data];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Incoming Set" message:[NSString stringWithFormat:#"%# wants to send you a Set named: \n\n %#",[session displayNameForPeer:peer], [dict valueForKey:#"SetName"]] delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil];
[alert show];
[alert release];
}
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
// the user clicked one of the OK/Cancel buttons
if (buttonIndex == 0)
{
//NSLog(#"ok");
//this should happen if the user presses on ok on the alertview.
[dataArray addObject:dict]; //i can't acess "dict"
}
else
{
//NSLog(#"cancel");
}
}
Do you see the problem?? What can I do??
dict is created as autorelease, so it will be deleted during UIAlertView show up.
Your CancelButton's index is == 0;
cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil
Seems, that your OK button index is 1.

UIAlertView Pops Up Three Times per Call Instead of Just Once

I am getting odd behavior from an NSAlert in two different parts of my program. The behavior is:
Alert appears and then spontaneously disappears.
Alert reappears and then remains until dismissed by user i.e. normal behavior.
Alert reappears again.
This behavior only occurs the first time the method that displays the alert is called. After that first time, it behaves normally.
Here is the code for the one of the parts in which the behavior occurs:
UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:#"You are in the right place." message:nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[locationAlert show];
[locationAlert release];
Or if you prefer, with a bit more context:
- (IBAction)locateMe {
NSLog(#"About to check location");
locMan = [[CLLocationManager alloc] init];
locMan.delegate = self;
locMan.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
locMan.distanceFilter = 1609; //1 mile
[locMan startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation * )oldLocation {
if (newLocation.horizontalAccuracy >= 0) {
CLLocation *airportLocation = [[[CLLocation alloc] initWithLatitude:51.500148 longitude:-0.204669] autorelease];
CLLocationDistance delta = [airportLocation getDistanceFrom: newLocation];
long miles = (delta * 0.000621371) + 0.5; //metres to rounded mile
if (miles < 3) {
UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:#"You are in the right place." message:nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[locationAlert show];
[locationAlert release];
[locMan stopUpdatingLocation];
} else {
UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:#"You are not in the right place." message:nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[locationAlert show];
[locationAlert release];
[locMan stopUpdatingLocation];
}
}
}
- (void) locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:#"Error." message:error.code delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[locationAlert show];
[locMan release];
locMan = nil;
}
Any ideas? Thanks.
Edit---------
The other place this happens is:
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
NSString * errorString = [NSString stringWithFormat:#"Unable to download feed from web site (Error code %i )", [parseError code]];
NSLog(#"error parsing XML: %#", errorString);
UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:#"Error loading content" message:errorString delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
For context the first case is in the AppDelegate and the second in the view controller for the 1st tab view. The second problem occurs every time the xml is reloaded when there is no internet connection. The first one only occurs the first time the function is called.
Edit-----
If I move the alert it works. Unfortunatly this is not where I want it!
- (IBAction)locateMe {
UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:#"You are in the right place." message:nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[locationAlert show];
/*
NSLog(#"About to check location");
locMan = [[CLLocationManager alloc] init];
locMan.delegate = self;
locMan.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
locMan.distanceFilter = 1609; //1 mile
[locMan startUpdatingLocation];*/
}
Update:
I set some NSLog entries and discovered that despite the addition of [locMan stopUpdatingLocation] the didUpdateToLocation function was running multiple times.
I guess the spontaneous disappearance happens because the alert view is called again and the programme clears the first instance to make way for the second automatically.
Any ideas as to why [locMan stopUpdatingLocation] doesn't work would be appreciated but in the mean time I just moved the declaration of the locationAlert out of the function (so it is global), set it in the initial locate me function and use the following the first time it is called:
[locationAlert show];
locationAlert = nil;
That way it works perfectly.
You're not turning off your location manager when you first show the alert. As the location is refined by the device (ie, the accuracy is increased), your callback will be (potentially) called multiple times. You should use [locMan stopUpdatingLocation] after your alert display.
I set some NSLog entries and discovered that despite the addition of [locMan stopUpdatingLocation] the didUpdateToLocation function was running multiple times.
I guess the spontaneous disappearance happens because the alert view is called again and the programme clears the first instance to make way for the second automatically.
Any ideas as to why [locMan stopUpdatingLocation] doesn't work would be appreciated but in the mean time I just moved the declaration of the locationAlert out of the function (so it is global), set it in the initial locate me function and use the following the first time it is called:
[locationAlert show];
locationAlert = nil;
That way it works perfectly.
I think the NSAlert disappearing on its own is the key to solving this.
It's simple to explain why an alert displays unexpectedly i.e. it's just been called unexpectedly. However, it's not so common to programmatically dismiss an alert. Whatever is causing it to disappear is most likely triggering the display again.
To debug I suggest:
(1) Looking in your code for the NSAlert – dismissWithClickedButtonIndex:animated: method and see if somehow you're actually dismissing the alert programmatically.
(2) I believe (someone double-check me on this) that an alert view is added as a subview to whichever base view is currently on screen. It might be that the base view is disappearing for some reason and taking the alert view with it. If the view disappears and then reappears rapidly enough, it might not be obvious when the alert is frontmost. (Edit: see Ed Marty's comment below.)
(3) Since this happens in two separate pieces of the app, compare both to find a common element or structure. That common element might be the cause.
An odd problem.
Edit01: Updated for additional info
If locMan isan instance variable, it should be defined as a property and you should access it every time withself.locMan By accessing it directly, you lose your automatic retention management.
I encountered the same exact issue with the alert dialog appearing momentarily, reappearing, and finally appearing again after being dismissed. I was making a string comparison before deciding to show the alert view:
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if([string isEqualToString:#"OK"]) {
NSLog(#"(Settings)Registration Successful");
statusField.text = #"Registration successful!";
[settingsActivity stopAnimating];
}
else {
NSLog(#"(Settings)Registration Failure");
[settingsActivity stopAnimating];
UIAlertView * regFail = [[[UIAlertView alloc] initWithTitle:#"Registration Error!" message:#"Please check your email address and try again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil] autorelease];
[regFail show];
}}
To correct this behavior I simply verified the returned string rather than just showing the alert:
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if([string isEqualToString:#"OK"]) {
NSLog(#"(Settings)Registration Successful");
statusField.text = #"Registration successful!";
[settingsActivity stopAnimating];
}
else if([string isEqualToString:#"Error"]) {
NSLog(#"(Settings)Registration Failure");
[settingsActivity stopAnimating];
UIAlertView * regFail = [[[UIAlertView alloc] initWithTitle:#"Registration Error!" message:#"Please check your email address and try again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil] autorelease];
[regFail show];
}
I also got the Same problem while working on Location Manager. Here i checked with Nslog but it is executing multiple times, finally i fount that i am creating multiple objects and using Sharedinstance for same ViewController that contains Location Manger but i am not releasing the object, so at perticular location how many objects if we create that many times the location detects.So while working on LocationManger check handling objects thoroughly to reduce these type of problems.