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.
Related
I have schedule UILocalNotification in my application at 10:00 AM Every Day.
I have used following code for this
NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar] ;
NSDateComponents *componentsForReferenceDate =
[calendar components:(NSDayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit ) fromDate:[NSDate date]];
[componentsForReferenceDate setDay:10] ;
[componentsForReferenceDate setMonth:10] ;
[componentsForReferenceDate setYear:2013] ;
NSDate *referenceDate = [calendar dateFromComponents:componentsForReferenceDate] ;
// set components for time 10:00 a.m.
NSDateComponents *componentsForFireDate =
[calendar components:(NSYearCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit| NSSecondCalendarUnit ) fromDate: referenceDate];
[componentsForFireDate setHour:10] ;
[componentsForFireDate setMinute:0] ;
[componentsForFireDate setSecond:0] ;
NSDate *fireDateOfNotification = [calendar dateFromComponents: componentsForFireDate];
// Create the notification
UILocalNotification *notification = [[UILocalNotification alloc] init] ;
notification.fireDate = fireDateOfNotification ;
notification.timeZone = [NSTimeZone localTimeZone] ;
notification.alertBody = [NSString stringWithFormat: #"Good Morning! Have a great day!"] ;
notification.alertAction = #"go back";
notification.userInfo= [NSDictionary dictionaryWithObject:[NSString stringWithFormat:#"Some information"] forKey:#"information"];
notification.repeatInterval = NSDayCalendarUnit ;
notification.soundName = UILocalNotificationDefaultSoundName;
notification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;
[[UIApplication sharedApplication] scheduleLocalNotification:notification] ;
It's working very good.
but now I want to schedule UILocalNotification at Every other day and every third day.
so how to do this?
You can not do customization of repeatTimeInterval of UILocalNotification.. there are many question as same like yours and also some days ago I had same question but i can not find any solution so please better is stop fight with it.
You must need to use repeat time interval from
Calendar Units
Specify calendrical units such as day and month.
enum {
NSEraCalendarUnit = kCFCalendarUnitEra,
NSYearCalendarUnit = kCFCalendarUnitYear,
NSMonthCalendarUnit = kCFCalendarUnitMonth,
NSDayCalendarUnit = kCFCalendarUnitDay,
NSHourCalendarUnit = kCFCalendarUnitHour,
NSMinuteCalendarUnit = kCFCalendarUnitMinute,
NSSecondCalendarUnit = kCFCalendarUnitSecond,
NSWeekCalendarUnit = kCFCalendarUnitWeek,
NSWeekdayCalendarUnit = kCFCalendarUnitWeekday,
NSWeekdayOrdinalCalendarUnit = kCFCalendarUnitWeekdayOrdinal,
NSQuarterCalendarUnit = kCFCalendarUnitQuarter,
NSWeekOfMonthCalendarUnit = kCFCalendarUnitWeekOfMonth,
NSWeekOfYearCalendarUnit = kCFCalendarUnitWeekOfYear,
NSYearForWeekOfYearCalendarUnit = kCFCalendarUnitYearForWeekOfYear
NSCalendarCalendarUnit = (1 << 20),
NSTimeZoneCalendarUnit = (1 << 21),
};
typedef NSUInteger NSCalendarUnit;
Above you can found from Apple's documentation. also read this question...
How to set Local Notification repeat interval to custom time interval?
For more information , you only scheduled local notification maximum 64, so be careful if may be you have planing in you mind that, you want to create multiple notification for do custom repeat time intervals..
You can't do this simply with repeatInterval, because only the following intervals are available.
One of the solutions I can think of would be to set separate notifications for each day (without repeatInterval). But by doing it in this way you can stumble on 64 notifications limit.
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 .
I looked at many pieces of codes but didn't get solution yet,
I simply need to get my app icon badge updated daily with some calendar (not gregorian) number of the day.
How can I do that?
I don't know how you would code it, but if you were going to submit such an app to the app store, apple wouldn't approve it. Apple's strict review guidelines can be frustrating, and like in this case, they limit functionality of your apps. Sorry :(
You obviously can't use repeating local notifications, because you want to specify an application badge number. Therefore you have to use one local notification for each day scheduled at midnight and with the appropriate badge number.
Because you can only schedule a maximum of 64 local notifications, you have to queue the notifications at each application launch.
This code isn't tested, there might be problems with daylight saving times, etc. (Works on iOS 4.2 or later, using ARC)
- (void) applicationDidBecomeActive:(UIApplication *)application {
NSUInteger startingDayAfterToday = [application.scheduledLocalNotifications count];
NSArray *localNotifications = [self localNotificationsStartingOnDayAfterToday:startingDayAfterToday];
NSArray *newScheduledNotifications = [application.scheduledLocalNotifications arrayByAddingObjectsFromArray:localNotifications];
[application setScheduledLocalNotifications:newScheduledNotifications];
}
- (NSArray *) localNotificationsStartingOnDayAfterToday:(NSUInteger)startingDayAfterToday {
NSMutableArray *localNotifications = [[NSMutableArray alloc] initWithCapacity:64 - startingDayAfterToday];
for (NSUInteger i = startingDayAfterToday; i < 64; i++) {
// Create a new local notification
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.hasAction = NO;
// Create today's midnight date
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; // Could be other calendar, too
NSDateComponents *todayDateComponents = [calendar components:(NSEraCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:[NSDate date]];
NSDate *todayMidnight = [calendar dateFromComponents:todayDateComponents];
// Create the fire date
NSDateComponents *addedDaysComponents = [[NSDateComponents alloc] init];
addedDaysComponents.day = i;
NSDate *fireDate = [calendar dateByAddingComponents:addedDaysComponents toDate:todayMidnight options:0];
// Set the fire date and time zone
notification.fireDate = fireDate;
notification.timeZone = [NSTimeZone systemTimeZone];
// Set the badge number
NSDateComponents *fireDateComponents = [calendar components:NSDayCalendarUnit fromDate:fireDate];
notification.applicationIconBadgeNumber = fireDateComponents.day;
// We're done, add the notification to the array
[localNotifications addObject:notification];
}
return [localNotifications copy];
}
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:].
I'm trying to learn Objective-C/iPhone SDK and right now I'm doing a kind of to-do app playing with local notifications.
I have a "timeOfDay" ivar stored as an NSDate from a DatePicker and a "numberOfDays" ivar stored as an NSNumber.
When I press a specific button, I would like to schedule a local notification x numberOfDays from the time the button is pressed but at the specific timeOfDay.
I seems easy to add an NSTimeInterval to the current date which would give me the a way to schedule the notification numberOfDays from current time but adding the timeOfDay feature makes it more complex.
What would be the correct way of achieving this?
Thanks
Use NSDateComponents to add time intervals to an existing date while respecting all the quirks of the user's current calendar.
NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
// Get the year, month and day of the current date
NSDateComponents *dateComponents = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit| NSDayCalendarUnit) fromDate:[NSDate date]];
// Extract the hour, minute and second components from self.timeOfDay
NSDateComponents *timeComponents = [calendar components:(NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:self.timeOfDay];
// Apply the time components to the components of the current day
dateComponents.hour = timeComponents.hour;
dateComponents.minute = timeComponents.minute;
dateComponents.second = timeComponents.second;
// Create a new date with both components merged
NSDate *currentDateWithTimeOfDay = [calendar dateFromComponents:dateComponents];
// Create new components to add to the merged date
NSDateComponents *futureComponents = [[NSDateComponents alloc] init];
futureComponents.day = [self.numberOfDays integerValue];
NSDate *newDate = [calendar dateByAddingComponents:futureComponents toDate:currentDateWithTimeOfDay options:0];
There is a pretty simple method to do this that won't involve as many lines of code.
int numDays = 5;
myDate = [myDate dateByAddingTimeInterval:60*60*24*numDays];
+ (id)dateWithTimeInterval:(NSTimeInterval)seconds sinceDate:(NSDate *)date
That should give you what you're looking for.