I am using UNUsernotification for iOS 10 and Xcode 8 Beta 2
I wrote below code for Local Notification in iOS device:
-(void) localNotificationForiOS10:(NSDate *) _reminderDate{
NSLog(#"_reminderDate %#",_reminderDate);
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
[calendar setTimeZone:[NSTimeZone localTimeZone]];
NSDateComponents *components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond|NSCalendarUnitTimeZone fromDate:_reminderDate];
NSLog(#"NSDateComponents %#",components);
UNMutableNotificationContent *objNotificationContent = [[UNMutableNotificationContent alloc] init];
objNotificationContent.title = [NSString localizedUserNotificationStringForKey:#"Event Name!" arguments:nil];
objNotificationContent.body = [NSString localizedUserNotificationStringForKey:#"You have event reminder"
arguments:nil];
objNotificationContent.sound = [UNNotificationSound defaultSound];
/// 4. update application icon badge number
objNotificationContent.badge = #([[UIApplication sharedApplication] applicationIconBadgeNumber] + 1);
UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:NO];
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:#"firedate"
content:objNotificationContent trigger:trigger];
/// 3. schedule localNotification
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (!error) {
NSLog(#"Local Notification succeeded");
}
else {
NSLog(#"Local Notification failed");
}
}];
}
I want to set three different or multiple future dates and want reminder of event on defined dates.
When I used the above code for 3 different time on same date
e.g. (2016-12-29 18:05 ,2016-12-29 18:10, 2016-12-29 18:15) than only last one gave notification.
I register Location notification in AppDelegate file.
application.applicationIconBadgeNumber = 0;
if ([[[UIDevice currentDevice] systemVersion] floatValue] > 10.0f) {
#if XCODE_VERSION_GREATER_THAN_OR_EQUAL_TO_8
/// schedule localNotification, the delegate must be set before the application returns from applicationDidFinishLaunching:.
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
#endif
} else {
UILocalNotification *localNotifacation = [self getLocalNotificationFromLaunchOptions:launchOptions];
if (localNotifacation) {
NSString *title = localNotifacation.alertBody;
NSLog(#"Add Title %#",title);
}
}
I tried my self and I tried it.
I am able to cancel the Local Notification in iOS 10.
here is posted code.
how to cancel a local notification in iphone
Related
I have local notification setup in one of my application which remind the user regarding medication on a regular basis and n times daily depends on user selection. If the user setup the reminder in the application and changes the date on device setting, reminder not triggering for the next scheduled time. But works fine for the other scheduled times. First notification scheduled is missing. Works fine for normal scenarios. Anyone faced similar issues? TIA. Code snippet as follows:
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center setNotificationCategories:[NSSet set]];
UNAuthorizationOptions options = UNAuthorizationOptionAlert + UNAuthorizationOptionSound + UNAuthorizationOptionBadge;
[center requestAuthorizationWithOptions:options
completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (!granted) {
PRLog(#"Something went wrong");
}else{
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] registerForRemoteNotifications];
});
[LocalNotificationShared registerCategories];
}
}];
}
and triggering part like:
NSDateComponents *triggerDate = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond|NSCalendarUnitTimeZone fromDate:date]; UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:triggerDate repeats:NO];
NSString *s = [NSString stringWithFormat:#"%#",#([NSDate timeIntervalSinceReferenceDate])];
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:s
content:content trigger:trigger];
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (error != nil) {
PRLog(#"Something went wrong: %#",error);
}
}];
From what I've observed, the time interval for a scheduled notification is independent of the device time. So if you schedule a notification for an hour away, and then set your device time to 59 minutes ahead, it won't matter - you will still have to wait the full hour for it to trigger.
I scheduled multiple Local Notification for the user. All of them are also delivered on their specified time. However, when I try to open any one of them from Notification Center, all of them are getting cleared.
In a rightful scenario, I don't want all them to be cleared from notification centre, only those which are tapped to be opened.
Also, i tried commenting below code from AppDelegate.m, but the issue still persists. [[UIApplicationsharedApplication]setApplicationIconBadgeNumber:0];
Can anyone tell me what could be the issue here due to which my scheduled notifications are cleared from Notification Center even when I'm tapping to open only one of them?
Below is the code I'm using to schedule Local Notifications -
NSDateComponents *components = [SSUtility hoursMinuteAndSectionsForDate:date];
NSInteger hour = [components hour];
NSInteger minute = [components minute];
NSLog(#"Hour %ld Min %ld ", hour,minute);
UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:YES];
/* Set notification */
UNMutableNotificationContent *content = [UNMutableNotificationContent new];
content.body = body;
// content.categoryIdentifier=NSNotificationC;
content.sound = [UNNotificationSound defaultSound];
content.userInfo = userInfo;
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier
content:content
trigger:trigger];
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (error != nil) {
SSLOG(#"Something went wrong: %#",error);
}
}];
So i did't believe that this is a default behaviour so what i found:
if you use UNCalendarNotificationTrigger then all delivered reminders are deleted on tap
if you use UNTimeIntervalNotificationTrigger then delivered reminders remain on the notification center
so try to use the UNTimeIntervalNotificationTrigger instead of UNCalendarNotificationTrigger
NSTimeInterval timeInterval = [fireDate timeIntervalSinceDate:[NSDate date]];
UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:timeInterval repeats:NO];
In my case, Add some text to content.body solve the problem:
content.body = 'Any text'
I have searched a lot to try to find a specific solution to this problem. I have an app that uses the former UILocalNotification system to send local notifications, and this still works fine under iOS 10.3.3. However, I have tried to convert this to the new UNNotification system because the former system is deprecated. No matter whether I try a UNCalendarNotificationTrigger or a UNTimeIntervalNotificationTrigger, the delegate does not receive a call. Here is the code for the triggering viewcontroller.
if (isItTime){
NSCalendar *currentCalendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
[currentCalendar setTimeZone:[NSTimeZone localTimeZone]];
NSDateComponents *components = [currentCalendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond | NSCalendarUnitTimeZone fromDate:[now dateByAddingTimeInterval:30]];
// components.second = 0;
NSLog(#"trigger components: %#", components);
UNCalendarNotificationTrigger* trigger = [UNCalendarNotificationTrigger
triggerWithDateMatchingComponents:components repeats:NO];
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:#"invite" content:content trigger:trigger];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(#"Something went wrong: %#",error);
}
}];
[self.currentLocalNotificationRequests addObject:request];
return request;
}else{
return nil;
}
And here is the code for the delegate (appdelegate) didFinishLaunching:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound)
completionHandler:^(BOOL granted, NSError * _Nullable error) {
// Enable or disable features based on authorization.
NSLog(#"_prefix:set($class $method $line)");
NSUserDefaults *storage = [NSUserDefaults standardUserDefaults];
if(granted == YES){
[storage setBool:YES forKey:#"permission granted"];
[storage setBool:YES forKey:#"alert permission granted"];
[storage setBool:YES forKey:#"sound permission granted"];
}else{
NSLog(#"No permission granted");
[storage setBool:NO forKey:#"permission granted"];
};
}];
Code for the appdelegate to get the notifications:
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler{
NSLog(#"appdelegate - center didReceiveNotificationResponse");
NSString *actionIdentifier = response.actionIdentifier;
UNNotification *notification = response.notification;
if([actionIdentifier isEqual:#"com.apple.UNNotificationDefaultActionIdentifier"] || [actionIdentifier isEqual:#"com.apple.UNNotificationDismissActionIdentifier"]){
}else{
BOOL accept = [actionIdentifier isEqual:#"ACCEPT_IDENTIFIER"];
BOOL stop = [actionIdentifier isEqual:#"DECLINE_IDENTIFIER"];
BOOL doNotDisturb = [actionIdentifier isEqual:#"DO_NOT_DISTURB_IDENTIFIER"];
if (accept){NSLog(#"accept");
[self handleAcceptActionWithNotification:notification];
}
else if (stop){NSLog(#"stop");
[self handleDeclineActionWithNotification:notification];
}
else if(doNotDisturb) {NSLog(#"do not disturb");
[self handleDoNotDisturbActionWithNotification:notification];
};
}
completionHandler();
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
NSLog(#"appdelegate willPresentNotification");
UNNotificationRequest * request = notification.request;
NSString * actionIdentifier = request.identifier;
if([actionIdentifier isEqualToString:UNNotificationDismissActionIdentifier] || [actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]){
}else{
if([actionIdentifier isEqualToString:#"invite"]){
NSLog(#"app delegate notification received while in foreground");
}
}
completionHandler(UNNotificationPresentationOptionAlert + UNNotificationPresentationOptionSound);
}
Here is the NSLog of the triggering code:
<NSDateComponents: 0x146d51c0>
TimeZone: America/Chicago (CDT) offset -18000 (Daylight)
Calendar Year: 2017
Month: 10
Leap month: no
Day: 29
Hour: 14
Minute: 3
Second: 4
It is very clear that appdelegate methods are not being called by the system (I did put the app in background before the notification time, so the didReceiveNotification method should have been called.
If anyone can help, I would appreciate it!
Also, this code in viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveNotificationFromAppDelegate:)
name:kAppDelegateNotification
object:nil];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(applicationBecameActive) name:UIApplicationDidBecomeActiveNotification object:nil];
self.currentLocalNotificationRequests = [[NSMutableArray alloc]init];
/*
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(checkDndIndicator) name:UIApplicationDidBecomeActiveNotification object:nil];
*/
UNNotificationAction *acceptAction = [UNNotificationAction actionWithIdentifier:#"ACCEPT_IDENTIFIER" title:NSLocalizedString(#"Continue notifications", nil) options:UNNotificationActionOptionAuthenticationRequired];
UNNotificationAction *declineAction = [UNNotificationAction actionWithIdentifier:#"DECLINE_IDENTIFIER" title:NSLocalizedString(#"Stop notifications", nil) options:UNNotificationActionOptionAuthenticationRequired];
UNNotificationAction *doNotDisturbAction = [UNNotificationAction actionWithIdentifier:#"DO_NOT_DISTURB_IDENTIFIER" title:NSLocalizedString(#"Start Do Not Disturb", nil) options:UNNotificationActionOptionAuthenticationRequired];
NSArray *actions = [NSArray arrayWithObjects:acceptAction, declineAction, doNotDisturbAction, nil];
// NSArray *intentIdentifiers = [NSArray arrayWithObjects:#"none", nil];
UNNotificationCategory *invite = [UNNotificationCategory categoryWithIdentifier:#"com.nelsoncapes.localNotification" actions:actions intentIdentifiers: #[] options:UNNotificationCategoryOptionNone];
NSSet *categories = [NSSet setWithObjects:invite, nil];
[center setNotificationCategories:categories];
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound)
completionHandler:^(BOOL granted, NSError * _Nullable error) {
// Enable or disable features based on authorization.
NSLog(#"request granted");
}];
And code to start the trigger process:
-(UNNotificationRequest *)startLocalNotification:(NSDate *)fireDate :
(NSMutableDictionary *)userInfo{
NSUserDefaults *storage = [NSUserDefaults standardUserDefaults];
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center removeAllPendingNotificationRequests];
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
content.title = NSLocalizedString(#"TimeChime Alert", nil);
content.body = NSLocalizedString(#"Click to Stop or Change Timer",nil);
content.categoryIdentifier = #"com.nelsoncapes.localNotification";
It turns out that this problem is obscure but the fix is easy. Unfortunately, I didn't carefully follow the first rule of coding: RTFD.
Apple's documentation for UNNotificationRequest> identifier states:
"If you use the same identifier when scheduling a new notification, the system removes the previously scheduled notification with that identifier and replaces it with the new one."
My code was using the same identifier for each UNNotificationRequest. Although the calendar notification date for each request was different, the system only kept the latest-dated request. In my case, the trigger would have fired after 1 hour, and I expected it to fire after 15 minutes. This is why I never saw a notification on the device and why I never saw a breakpoint in the delegate's didReceiveNotificationResponse method.
The fix is very easy. Just supply a unique identifier in the following code. After that, the code works.
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:#"invite" content:content trigger:trigger];
Replace #"invite" with a unique identifier for each request.
I was not getting my notification because I did not specify the required date components to pass to my UNCalendarNotificationTrigger.
This does not work:
NSDateComponents *dateComponents = [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour) fromDate:[[NSDate date] dateByAddingTimeInterval:5]];
This works:
NSDateComponents *dateComponents = [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond | NSCalendarUnitNanosecond) fromDate:[[NSDate date] dateByAddingTimeInterval:5]];
My application in background or inactive mode then local notification not work. I have never receive local notification on watch.
Update: less then 3 minutes schedule a local notification it's work fine but more then 3 minutes it's not work. so how to resolve this issues?
As per my understanding My code is as follows.
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
// Objective-C
UNMutableNotificationContent *content = [UNMutableNotificationContent new];
content.title = [NSString localizedUserNotificationStringForKey:#"Remider!" arguments:nil];
content.body = [NSString localizedUserNotificationStringForKey:#"Your watch is out of range" arguments:nil];
content.sound = [UNNotificationSound defaultSound];
// Time
// 15 min
double timer = 15*60;
UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:time
repeats:NO];
// Actions
UNNotificationAction *snoozeAction = [UNNotificationAction actionWithIdentifier:#"Track"
title:#"Track" options:UNNotificationActionOptionForeground];
// Objective-C
UNNotificationCategory *category = [UNNotificationCategory categoryWithIdentifier:#"UYLReminderCategory"
actions:#[snoozeAction] intentIdentifiers:#[]
options:UNNotificationCategoryOptionCustomDismissAction];
NSSet *categories = [NSSet setWithObject:category];
// Objective-C
[center setNotificationCategories:categories];
// Objective-C
content.categoryIdentifier = #"UYLReminderCategory";
NSString *identifier = [self stringUUID];
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier
content:content trigger:trigger];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(#"Something went wrong: %#",error);
}
}];
Appreciate if any suggestion or idea.
Make sure your iphone is locked. When it comes to notification, its about preference where to deliver that notification.
Run your watch app on simulator, from iPhone simulator schedule the notification and lock the iPhone simulator screen, keep the watch simulator active, in that case when notification is triggered , it will be delivered on your watch simulator. Same will be the case when you will test on actual devices.
Source Link
And when both iphone and watch is locked, preference is iphone.
UPDATE
Notification on Apple Watch
In local notifications there is repeatInterval property where we can put the unit repeat intervals for minute, hour, day, week, year, etc.
I want that repeat interval on Prayer time hours and every day same process.
So every Prayer time hours the local notification comes.
Prayer time is everyday different times
You can't do it with repeat. Make a bunch of different make notifications - one for each day - for the next 30 days. When the user opens the app, then recreate them for the next 30.
You can set repeat interval as day and pass array of local notifications of different time.
myapp.scheduledLocalNotifications = arrayOfNOtifications;
this may help you : how to create multiple local notifications
i have done a app like this try this .
func scheduleNotification() {
let dateString = "2017-04-04 09:00:00"
let dateFormatter = DateFormatter()
var localTimeZoneName: String { return TimeZone.current.identifier }
var secondsFromGMT: Int { return TimeZone.current.secondsFromGMT() }
dateFormatter.timeZone = TimeZone(secondsFromGMT: secondsFromGMT)
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let dateObj:Date = dateFormatter.date(from: dateString)!
let triggerDaily = Calendar.current.dateComponents([.hour,.minute,.second,], from: dateObj)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: true)
let content = UNMutableNotificationContent()
content.title = "mIdeas"
content.body = getRandomMessage()
content.sound = UNNotificationSound.default()
content.categoryIdentifier = "myCategory"
let request = UNNotificationRequest(identifier: "textNotification", content: content, trigger: trigger)
UNUserNotificationCenter.current().delegate = self
//this commented code is to remove the pre-seted notifications so if you need multiple times don't use this line of code
//UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
UNUserNotificationCenter.current().add(request) {(error) in
if let error = error {
print("Uh oh! i had an error: \(error)")
}
}
}
call this function to set notification you can modify this func and add parameters to pass time
Yes you can push a notification at a particular time and day with a repeat option.
Follow the code below:
//1. catch the notif center
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
//2. I prefer removing any and all previously pending notif
[center removeAllPendingNotificationRequests];
//then check whether user has granted notif permission
[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
if (settings.authorizationStatus != UNAuthorizationStatusAuthorized) {
// Notifications not allowed, ask permission again
[center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert)
completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (!error) {
//request authorization succeeded!
}
}];
}
}];
//3. prepare notif content
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = [NSString localizedUserNotificationStringForKey:NSLocalizedString(#"Hello! Today's Sunday!!",nil) arguments:nil];
content.body = [NSString localizedUserNotificationStringForKey:NSLocalizedString(#"Sleep tight!",nil) arguments:nil];
content.sound = [UNNotificationSound defaultSound];
content.badge = #([[UIApplication sharedApplication] applicationIconBadgeNumber] + 1);
//4. next, create a weekly trigger for notif on every Sunday
NSDate* sundayDate = startDate;
NSDateComponents *components = [[NSDateComponents alloc] init];
while(true){
NSInteger weekday = [[NSCalendar currentCalendar] component:NSCalendarUnitWeekday fromDate:sundayDate];
if(weekday == 1){//sunday, stay asleep reminder . LOL
components.weekday = 1;
components.hour = 9;
components.minute = 0;
break;
}else{//keep adding a day
[components setDay:1];
sundayDate = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:sundayDate options:0];
}
}
//5. Create time for notif on Sunday
unsigned unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *comps = [calendar components:unitFlags fromDate:sundayDate];
comps.hour = 9;
comps.minute = 0;
sundayDate = [calendar dateFromComponents:comps];
NSDateComponents *triggerWeekly = [[NSCalendar currentCalendar] components:NSCalendarUnitWeekday + NSCalendarUnitHour + NSCalendarUnitMinute fromDate:sundayDate];
UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:triggerWeekly repeats:YES];
//6. finally, add it to the request
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:#"LocalIdentifier" content:content trigger:trigger];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (!error) {
NSLog(#"Local Notification succeeded");
} else {
NSLog(#"Local Notification failed");
}
}];
If you are looking for actionable items on the notification. You should add it somewhere in the center.
UNNotificationAction *snoozeAct = [UNNotificationAction actionWithIdentifier:#"Snooze"
title:NSLocalizedString(#"Snooze",nil) options:UNNotificationActionOptionNone];
UNNotificationAction *deleteAct = [UNNotificationAction actionWithIdentifier:#"Delete"
title:NSLocalizedString(#"Delete",nil) options:UNNotificationActionOptionDestructive];
UNNotificationCategory *category = [UNNotificationCategory categoryWithIdentifier:identifier
actions:#[snoozeAct,deleteAct] intentIdentifiers:#[]
options:UNNotificationCategoryOptionNone];
NSSet *categories = [NSSet setWithObject:category];
[center setNotificationCategories:categories];
content.categoryIdentifier = #"ActionIdentifier";
Make sure you set a different identifier for your notification request!