UILocal notifications not showing - iphone

I can't get my local notifications to show. I am testing on the iphone. They do not show up at all and the date generated seems to be an hour before the one entered. 19 becomes 18 and so on.
How do I enable these local notifications at 7 while taking into account the user's time zone?
NSCalendar* myCalendar = [NSCalendar currentCalendar];
NSDateComponents* components = [myCalendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:[NSDate date]];
[components setHour: 19];
[components setMinute:00];
NSDate *todayAt7 = [myCalendar dateFromComponents:components];
UILocalNotification *dailyNotification = [[UILocalNotification alloc] init];
dailyNotification.fireDate = todayAt7; // set this to 7pm
dailyNotification.timeZone = [NSTimeZone defaultTimeZone];
dailyNotification.repeatInterval = NSDayCalendarUnit;
dailyNotification.soundName = UILocalNotificationDefaultSoundName;
dailyNotification.alertBody = #"You need to enter data for today.";

The first issue is that when you are creating he components instance, you are not asking for the hour and minutes components. Also, you should use NSCalendar *myCalendar = [NSCalendar autoupdatingCurrentCalendar]; instead of currentCalendar.
Second issue, at least your not showing the code for it, but you're not actually scheduling the notification object. See [UIApplication scheduleLocalNotification:].

Related

Update application badge once a day

This is the code I have and I it puts the date in a application badge. I was wondering how to reload this number everyday without entering the app to reload it. Thanks in advance!
NSDate *today = [NSDate date];
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *comp = [cal components:NSDayCalendarUnit fromDate:today];
NSInteger day = [comp day];
[UIApplication sharedApplication].applicationIconBadgeNumber = day;
A relatively easy way would be to put the code that sets the badge in the background. You can use [UIApplication beginBackgroundTaskWithExpirationHandler] or a related call for this purpose. The only problem is that there's a 10 minute limit for such execution. Having said that, there are tricks that can be used to circumvent that limit. Here is an excellent thread that discusses this topic: Run app for more than 10 minutes in background
I have following code :
NSDate *fireTime = [[NSDate date] addTimeInterval:3600*24];
notification.fireDate = fireTime;
notification.alertBody = #"Your Message!";
notification.applicationIconBadgeNumber = 1;
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
If you are testing on simulator then probably that is the reason why you are not getting the output. Test it on device and see whether is it working .

UILocalNotification fire when i open the notification tray to see the notification

i used the local notification and schedule the fire date but when the app is in background and i open the notification tray to see the notification then the local notification is fire automatically but the fire date is remaining..is there any solution to solve that problem
This sounds like you have two issues. First, the local notification has been created with a fire date set in the past - that's why its appearing as soon as you open the app.
Secondly, you may be setting the notification's repeatInterval to a non-zero value, which will cause it to come up more than once.
See the below code for setting a local notification to fire at 3pm:
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.alertBody = #"This is a test alert";
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setHour: 15];
[comps setMinute: 0];
[comps setSecond: 0];
NSDate *threePM = [currentCalendar dateFromComponents:comps];
// Test if the current time is after three or not:
if(threePM != [threePM earlierDate: [NSDate date]])
{
comps = [[NSDateComponents alloc] init];
[comps setDay: 1];
threePM = [currentCalendar dateByAddingComponents: comps toDate: threePM options: 0];
}
localNotification.fireDate = threePM;
localNotification.repeatInterval = 0;
[[UIApplication sharedApplication] scheduleLocalNotification: localNotification];

Updating local notification BadgeNumber

I am trying to show Today's date with the application badge number, this date should be updated when the application fires a Local Notification, but the problem is the local notification does not update the date ! and shows only date of the day on which my project was created ! here is my code :
- (void) viewDidLoad {
[self notification];
}
- (void) notification {
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *now = [NSDate date];
NSDateComponents *componentsForFireDate = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit| NSSecondCalendarUnit ) fromDate: now];
[componentsForFireDate year];
[componentsForFireDate month];
[componentsForFireDate day];
[componentsForFireDate setHour:1];
[componentsForFireDate setMinute:2];
[componentsForFireDate setSecond:1];
NSDate *fireDateOfNotification = [calendar dateFromComponents: componentsForFireDate];
UILocalNotification *notification = [[UILocalNotification alloc]init];
notification.fireDate = fireDateOfNotification;
notification.timeZone = [NSTimeZone localTimeZone]; notification.repeatInterval= NSDayCalendarUnit;
NSString *date = [self showGregorianFullDate];
notification.alertAction = #"View";
notification.soundName = UILocalNotificationDefaultSoundName;
//updating badge number :
NSCalendar* Calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *Components = [Calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit )fromDate:[NSDate date]];
int a = [Components day];
notification.applicationIconBadgeNumber = a;
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
Do you only schedule this one notification? When notifications fire they don't get to run any code. If your app is open you can handle the notification, and if the user takes action on your notification you are again given a chance to handle it.
This notification is programmed to set the badge number to a certain day number. That number is a fixed number. It won't change automatically when the notification has been fired.
The application badge is designed to show a number of unhandled notifications (as per the Human Interface Guidelines) and so may not be the best place to show a date. Also if you look at the app store review guidelines any app which uses system provided items in a way not described in the Human interface Guidelines could be rejected from the app store.
If you continue down this path then you may want to look at the Local Notification Programming Guide. It shows each app can have 64 local notifications scheduled, and that you would need to schedule one every day to update the badge number to the next day. This means that if the user doesn't open your app for 65 days the badge number will be wrong, and you would also have no local notifications left for user alerts.
Just get the day from componentsForFireDate for your notification.applicationIconBadgeNumber, just like this...
//updating badge number :
int a = [componentsForFireDate day];
notification.applicationIconBadgeNumber = a;
The thing is that applicationIconBadgeNumber has to be pre-determined at the time you create the notification. If you get the day from [NSDate date], it will show the day you create the notification not the day that the notification fires.

How to store and compare time data objects

This should be really simple!
I have a shop, it opens at 8:30 and closes at 17:00. I want my app to say the shops current open or currently closed.
Whats the best way to store my open_time and close_time? Store them as seconds since the start of the day, i.e. 30600 and 63000?
This make sense, but how do I get the current time right now, in seconds since the begining of today, so I can check if current_time is between open_time and close_time, i.e. open!!
Thanks in advance!
This problem isn't quite as trivial as you may think. You have to work with dates very carefully. The best solution is to store all of your open and close times as dates. Here is some code for creating your open/close times and comparing them:
NSDate * now = [NSDate date];
NSCalendar * calendar = [NSCalendar currentCalendar];
NSDateComponents * comps = [calendar components:~(NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:now];
[comps setHour:8];
[comps setMinute:30];
NSDate * open = [calendar dateFromComponents:comps];
[comps setHour:17];
[comps setMinute:0];
NSDate * close = [calendar dateFromComponents:comps];
if ([now compare:open] == NSOrderedDescending && [now compare:close] == NSOrderedAscending) {
// The date is within the shop's hours.
}
else {
// The date is not within the shop's hours.
}
Here's what I did:
Grab the current date.
Get the components of the date, except hours, minutes, and seconds.
Set the hour and minutes.
Create an open time.
Repeat steps 3-4 for close time.
Compare open and close times to now.
If you ever need to do any modification of dates, you should always use NSCalendar and NSDateComponents. Check out this answer for why it's so important.
I think a clearer solution would be to use NSDate objects with only hour/minute components present.
Basically, somewhere in your app you need to store the shop's open/close times as such:
NSCalendar *calendar = [[NSCalendar alloc]
initWithCalendarIdentifier: NSGregorianCalendar];
NSDateComponents *openTime = [[NSDateComponents alloc] init];
[openTime setHour: 12];
[openTime setMinute: 30];
NSDate *openDate = [calendar dateFromComponents: openTime];
[calendar release];
And if you need to see whether the current time is between two such NSDate objects you could have a method like this:
- (BOOL)currentTimeIsInBetween: (NSDate *)date1 andDate: (NSDate *)date2 {
NSCalendar *calendar = [[NSCalendar alloc]
initWithCalendarIdentifier: NSGregorianCalendar];
NSDateComponents *currentComponents = [calendar components:
(NSMinuteCalendarUnit | NSHourCalendarUnit)
fromDate: [NSDate date]];
NSDate *currentAdjusted = [calendar dateFromComponents: currentComponents];
[calendar release];
if ([currentAdjusted compare: date1] == NSOrderedAscending)
return NO;
if ([currentAdjusted compare: date2] == NSOrderedDescending)
return NO;
return YES;
}
EDIT: Seems like user rbrown was a bit faster than me, we are suggesting the same approach.
You can do something like this.
NSDate *today = // code for getting today date at 0 oclock
NSDate *now = [NSDate date];
double second = [now timeIntervalSinceDate:today];
Now you got time in second since the start of the day for compare.

Pass value of kCFCalendarUnitWeekday

I want to set an alarm on a particular day. I don't understand how to set the value of kCFCalendarUnitWeekday. Here is my code:
NSDateComponents *components = [[NSDateComponents alloc] init];
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
localNotif.fireDate = selected;
localNotif.timeZone = [NSTimeZone defaultTimeZone];
localNotif.repeatCalendar = [NSCalendar currentCalendar];
if (isSun) {
[components setWeekday:1];
[localNotif setRepeatInterval:(NSInteger)components];
}
if (isMon) {
[components setWeekday:2];
[localNotif setRepeatInterval:(NSInteger)components];
}
Thank you.
Ok here is some code to get you in the right direction:
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorian components:NSWeekdayCalendarUnit|NSYearCalendarUnit|NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit fromDate:[NSDate date]];
// this will set the weekday to sunday
[components setWeekday:1];
// this is a new date on sunday
NSDate * newDate = [gregorian dateFromComponents:components];
You still have to find out whether the newDate is in the past, so it won't fire.
You actually have your code ready:
// ... init code ...
// *** this the important date ***
localNotif.fireDate = dateOnASunday;
localNotif.timeZone = [NSTimeZone defaultTimeZone];
localNotif.repeatCalendar = NSWeekCalendarUnit;
... // add body etc. ...
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
[localNotif release];
Create a method around this snippet and pass the date with a parameter so you can reuse it. You only have to put in a date which should be the first fire date and it'll repeat every week. You just have to pass in a date on a Sunday or Wednesday.
You set a repeat interval like this:
// repeats notification on a weekly basis
localNotif.repeatCalendar = NSWeekCalendarUnit;
The repeatCalender property is of type NSCalendarUnit which is an enum.