Not the NSTimer or the applicationSignificantTimeChange then what do I use? - iphone

I want text to change once a day even if my app is not open at the time NSTimer doesn't run while your app is closed, applicationSignificantTimeChange won't get the message if my app is closed either.
What I need to do is.
(1) get the current date
(2) choose a phrase based on the current date and
(3) update your label
I still might use NSTimer or applicationSignificantTimeChange to handle the case where my app is open at midnight, but I need to get the phrase-picking method working first so my timer or time change method can call it at midnight for the new date
Can anyone help me out with this problem and what I need to do to make it work?

I hope this code is good enough to stop all the similar questions you are asking way too often.
Yes, lesson for the future: bug me with a lot of questions in categories I'm interested in and I will deliver the code.
- (void)updateLabelForDate:(NSDate *)date {
NSTimeInterval timeInterval = [date timeIntervalSinceReferenceDate];
NSInteger days = timeInterval / (60*60*24);
NSArray *sloganArray = [NSArray arrayWithObjects:
NSLocalizedString(#"Slogan for day 1", nil),
NSLocalizedString(#"Slogan for day 2", nil),
NSLocalizedString(#"Slogan for day 3", nil),
NSLocalizedString(#"I'll hope you'll get it", nil),
nil];
NSInteger usedSloganIndex = (int)days % [sloganArray count];
NSString *slogan = [sloganArray objectAtIndex:usedSloganIndex];
NSLog(#"Slogan: %#", slogan);
}
- (void)applicationSignificantTimeChange:(UIApplication *)application {
[self updateLabelForDate:[NSDate date]];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self.window addSubview:viewController.view];
[self.window makeKeyAndVisible];
[self updateLabelForDate:[NSDate date]];
// the following is there to prove that this code works.
NSDate *date = [NSDate date];
for (int i = 0; i < 10; i++) {
NSLog(#"Date: %#", date);
[self updateLabelForDate:date];
date = [date dateByAddingTimeInterval:(60*60*24)];
}
return YES;
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[self updateLabelForDate:[NSDate date]];
}

You can't, if the application isn't running.
You can however use a "Local Notification" - which is sort of like a "Push Notification" - except it is sent by your own device - to tell you that the app needs attention. This can be scheduled.
http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Introduction/Introduction.html

Related

How to fire action on date change?

I have SQLite database.
I want to insert row in database when date changes.
I just know that i should use UILocalNotification,But I don't know how.
Other way is to run NSTimer in background but I don't want to do that.
From tutorial I tried:
UIApplication* app = [UIApplication sharedApplication];
NSDate *date = [NSDate date];
// create the notification and then set it's parameters
UILocalNotification *notification = [[[UILocalNotification alloc] init] autorelease];
if (notification)
{
notification.fireDate = date;
notification.timeZone = [NSTimeZone defaultTimeZone];
notification.repeatInterval = 0;
notification.alertBody = #"DONE:";
// this will schedule the notification to fire at the fire date
[app scheduleLocalNotification:notification];
// this will fire the notification right away, it will still also fire at the date we set
[app presentLocalNotificationNow:notification];
}
But in my app it should insert in database either app is in background or foreground. Insertion should place when date changes.
If you want to go with UILocalNotification then see below information.
Set fireDate of UILocalNotification as you need and your notification will generated on this date.
And you will get generated notification at 2 (Two) ways. such like,
1) in didFinishLaunchingWithOptions
=> it is helpful if your application is not running;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
.
.
.
UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotif)
{
/// do your stuff
}
.
.
}
2) use delegate method of UILocalNotification
=> it is helpful if your application is running;
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif {
/// do your stuff
}
You can write your insert data here;
Add this code in didFinishLaunchingWithOptions method
// date change
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(dateChange) name:UIApplicationSignificantTimeChangeNotification object:nil];
Implement method in YourDelegate.m file
-(void)dateChange
{
if ([[NSUserDefaults standardUserDefaults] objectForKey:#"LastAppOpenTime"] != nil)
{
NSDate *lastDate = [[NSUserDefaults standardUserDefaults] objectForKey:#"LastAppOpenTime"];
NSDate *currentDate = [NSDate date];
NSTimeInterval distanceBetweenDates = [currentDate timeIntervalSinceDate:lastDate];
double secondsInAnHour = 3600;
NSInteger hoursBetweenDates = distanceBetweenDates / secondsInAnHour;
if (hoursBetweenDates >= 24)
{
//update database here.
}
}
[[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:#"LastAppOpenTime"];//Store current date
}
You can store [NSDate date]; to some variable and put condition according to last date and change that variable inside that condition with today's date with the use of [NSDate date]; and do modifications as you want.

UIApplication -scheduleLocalNotification: very slow when called by UIApplication -appWillTerminate:

I set the "application does not run in background" in my info.plist, so when user tap home button, app quits.
When my [UIApplication -appWillTerminate:] called, I will schedule 64 local notifications to system, all of them are non-repeating.
but that take a seemingly long time(6.17 seconds) on a iPhone4 with iOS6.0.1.
When I look at the time profiler, I found that the curve is very strange, it don't take much CPU time, but it do take a lot of time.
Also when I look at the call tree, 93% of the time is spent on [UIApplication -scheduleLocalNotification:] in the time range showed in the image.
Why?
This is how I generate my notifications:
UILocalNotification *n = [[[UILocalNotification] alloc] init] autorelease];
n.alertBody = #"some body";
n.hasAction = YES;
n.alertAction = #"some action";
n.fireDate = #"some date";
n.repeatInterval = 0;
n.soundName = #"my sound"
n.userInfo = aDictionaryWithAStringAbount10CharacterLongAnd2NSNumber.
[self.notifications addObject:n];
This is how I schedule my notifications:
-(void)endProxyAndWriteToSystemLocalNotification
{
_proxying = NO;
NSDate *dateAnchor = [NSDate date];
NSEnumerator *enumerator = [self.notifications objectEnumerator];
NSInteger i = 0;
while (i < maxLocalNotifCount) {
UILocalNotification *n = [enumerator nextObject];
if (!d) {
break;
}
if ([n.fireDate timeIntervalSinceDate:dateAnchor] >= 0) {
[[UIApplication sharedApplication] scheduleLocalNotification:n];
i++;
}
}
[self.notificationDatas removeAllObjects];
}
This would help:
-(void)endProxyAndWriteToSystemLocalNotification {
[[UIApplication sharedApplication] setScheduledLocalNotifications:self.notifications];
}
iOS 4.2 and later
read UIApplication Class Reference for detailed description
I think the problem is that you are trying to schedule 64 local notifications. Is there a reason to do all of these on app termination? Apples scheduleLocalNotification was not designed to be called so many times on termination

iOS: Local Notifications Don't Fire On Time

The issue is that my notifications aren't going through when they are set up to. I put a date picker in the nib and a button underneath it. The user is supposed to set the date in the picker, and clicking the button set up the notification to fire 60 hours before the date. So, it looks like I'm just having issues with getting the firedate to recognize the date in the date picker. Here is the code, it is in my view controller:
- (IBAction)scheduleNotifButton:(id)sender {
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
NSDate *selectedDate = [self.datePicker date];
localNotif.fireDate = [selectedDate dateByAddingTimeInterval:-60*60*60];
localNotif.timeZone = [NSTimeZone defaultTimeZone];
localNotif.alertBody = #"Event is in three days!";
localNotif.alertAction = nil;
localNotif.soundName = UILocalNotificationDefaultSoundName;
localNotif.applicationIconBadgeNumber = 0;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Event scheduled."
message:#"You will be notified three days before the event."
delegate:nil
cancelButtonTitle:#"Okay."
otherButtonTitles:nil];
[alert show];
}
And here is some additional code if that helps, this is more code from my view controller that deals with saving the date in the picker that the user entered:
- (IBAction)dateChanged:(id)sender
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDate *selectedDate = [self.datePicker date];
[defaults setObject:selectedDate forKey:#"ImportantDatesViewController.selectedDate"];
[defaults synchronize];
}
- (void)viewDidLoad {
NSDate *storedDate = [[NSUserDefaults standardUserDefaults]
objectForKey:#"ImportantDatesViewController.selectedDate"];
if (storedDate == nil) {
storedDate = [NSDate date];
}
[self.datePicker setDate:storedDate animated:NO];
}
I've been digging through this code for 3 days now and cannot figure out why my notifications aren't going through when they are supposed to. Any help is very much appreciated, thank you!
Do you understand that UILocalNotifications and remote notifications are different things?
In didRegisterForRemoteNotificationsWithDeviceToken you get the device token to be used for remote notifications. Remote notifications are sent from a server so you have to save that token on your server and then use your server to send any remote notifications.
Why don't you change this:
localNotif.fireDate = [eventDate dateByAddingTimeInterval:-630*60];
to this:
localNotif.fireDate = [[NSDate date] dateByAddingTimeInterval:60];
Then the local notification should go off in a minute. Maybe the problem is the date that you are setting.
How do you know your notifications aren't working?
Local and push notifications are different. If your app is currently active, a local notification won't actually show an alert message. It will just call a UIApplicationDelegateMethod
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification

How to initialize local notification?

I want to implement local notification in my clock app.Basically i want that a music file should be played after every half an hour like in ship's clock in which chimes are played after every 30 minutes.
Can anyone give rough idea as how i can implement this functionality even when the app enters in background?
I recently used the Local notification stuff and used the following functions
//Setting up the Local Notifications
for (int i= 1 ; i<=10; i++) { //We here set 10 Notification after every 30 minutes from now you can modify it accordingly
NSDate *scheduled = [[NSDate date] dateByAddingTimeInterval:60*30*i]; //These are seconds
NSDictionary* dataDict = [NSDictionary dictionaryWithObjectsAndKeys:scheduled,FIRE_TIME_KEY,#"Background Notification received",NOTIFICATION_MESSAGE_KEY,nil];
[self scheduleNotificationWithItem:dataDict];
}
Where scheduleNotificationWithItem is defined as
- (void)scheduleNotificationWithItem:(NSDictionary*)item {
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
if (localNotification == nil) return;
localNotification.fireDate = [item valueForKey:FIRE_TIME_KEY];
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.alertBody = [NSString stringWithFormat:NSLocalizedString(#"%#", nil), [item valueForKey:NOTIFICATION_MESSAGE_KEY]];
localNotification.alertAction = NSLocalizedString(#"View Details", nil);
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.userInfo = item;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
[localNotification release];
}
Finally you can handle these notifications as
You can handle these notifications as follows
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
// Do the required work you can obtain additional Info via notification.userInfo which happens to be a dictionary
}
reading the developer documentation will help you more to understand the stuff.Hope it helps
You can use UILocalNotifications and set their 'firedate', according to your requirement and then schedule the notification. These notifications doesn't bother whether your app is running or is in background they will always show up like an alertview.

Setting Local Notifications on a new thread?

I need to know if it is possible to create a new thread to handle setting local notifications.
My app depends heavily on these notifications, so I want to make the app work while the phone sets the notifications.
Example:
(now)
you launch the app, the app hangs at the splash screen to set the local notifications, then it launches.
(I want)
The app launches and is usable while the Local notifications are set.
I need some sample code, too, please :)
(for the record, i am setting 60 local notifications each time the app enters foreground for my own reasons...)
Thanks!!
Yes this can be done, I do it all the time:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Add the navigation controller's view to the window and display.
[NSThread detachNewThreadSelector:#selector(scheduleLocalNotifications) toTarget:self withObject:nil];
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
return YES;
}
-(void) scheduleLocalNotifications
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
for (int i = 0; i < 60; i++)
{
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
NSDate *sleepDate = [[NSDate date] dateByAddingTimeInterval:i * 60];
NSLog(#"Sleepdate is: %#", sleepDate);
localNotif.fireDate = sleepDate;
NSLog(#"fireDate is %#",localNotif.fireDate);
localNotif.timeZone = [NSTimeZone defaultTimeZone];
localNotif.alertBody = [NSString stringWithFormat:NSLocalizedString(#"This is local notification %i"), i];
localNotif.alertAction = NSLocalizedString(#"View Details", nil);
localNotif.soundName = UILocalNotificationDefaultSoundName;
localNotif.applicationIconBadgeNumber = 1;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
NSLog(#"scheduledLocalNotifications are %#", [[UIApplication sharedApplication] scheduledLocalNotifications]);
[localNotif release];
}
[pool release];
}
Taken from a project I am working on now, I can confirm that It works as expected.
EDIT:
Example was leaking in scheduleLocalNotifications because handling the NSAutoreleasePool was missing – now it's added to the example.
One way to do threads is with is with performSelectorInBackground.
For example:
[myObj performSelectorInBackground:#selector(doSomething) withObject:nil];
You should note, however, that Apple is pretty strongly recommending that you use higher-level concepts like NSOperations and Dispatch Queues instead of explicitly spawning threads. See the Concurrency Programming Guide