iOS locale notification pop-up doesn't appear - ios

I'm a newbie in iOS programming and in my app I've a UILocaleNotification which have to appear at a certain time.
So first I setup parameters :
let notificationSettings: UIUserNotificationSettings! = UIApplication.sharedApplication().currentUserNotificationSettings()
if (notificationSettings.types == UIUserNotificationType.None) {
var notificationTypes: UIUserNotificationType = UIUserNotificationType.Alert | UIUserNotificationType.Sound
// Bouton d'envoi
var sendAction = UIMutableUserNotificationAction()
sendAction.identifier = "send"
sendAction.title = "Send"
sendAction.activationMode = UIUserNotificationActivationMode.Foreground
sendAction.destructive = false
sendAction.authenticationRequired = true
// Bouton de non-envoi
var dontSendAction = UIMutableUserNotificationAction()
dontSendAction.identifier = "dontsend"
dontSendAction.title = "Don't send"
dontSendAction.activationMode = UIUserNotificationActivationMode.Background
dontSendAction.destructive = true
dontSendAction.authenticationRequired = false
let actionsArray = NSArray(objects: sendAction, dontSendAction)
var reminderNotification = UIMutableUserNotificationCategory()
reminderNotification.identifier = "reminderNotification"
reminderNotification.setActions(actionsArray as [AnyObject], forContext: UIUserNotificationActionContext.Minimal)
let categoriesForSettings = NSSet(objects: reminderNotification)
let newNotificationSettings = UIUserNotificationSettings(forTypes: notificationTypes, categories: categoriesForSettings as Set<NSObject>)
UIApplication.sharedApplication().registerUserNotificationSettings(newNotificationSettings)
}
... and I schedule my notification like that :
var localNotification = UILocalNotification()
localNotification.fireDate = NSDate(timeIntervalSinceNow: 3)
localNotification.timeZone = NSTimeZone.defaultTimeZone()
localNotification.alertBody = "Hey, inform your contacts !"
localNotification.alertAction = "Send Message"
localNotification.category = "reminderNotification"
localNotification.soundName = UILocalNotificationDefaultSoundName
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
When I try this code, notifs are displaying right in the notification center, but there is no pop-up displayed...
I searched sources on the net and I don't understand why those examples and tutos are displaying pop-up because I wrote the same code...
Thanks for your help and have a good day !
EDIT : I forgot something : it's the notification center which have to detect an event, and not the locale notification. So I want the addObserver of the notification center to check an event, is it possible in background state ?

According to this line: localNotification.fireDate = NSDate(timeIntervalSinceNow: 3) you want your notification to be triggered 3 seconds later. I assume that the app is still in the foreground when it happens. If it's the case, you will not have a notification popup.
If the app linked to a notification is opened when the notification is received, it has to handle it in your AppDelegate to display a custom popup.
func application(application: UIApplication!, didReceiveLocalNotification notification: UILocalNotification!) {
// do your jobs here
}

Related

UILocalNotifications not firing when scheduled

Well, none of the existing discussions presented a working solution for me. So here's my code to show local notifications. What am I missing?
let notification = UILocalNotification()
notification.alertBody = "Reminder" // text that will be displayed in the notification
notification.alertAction = "open"
notification.applicationIconBadgeNumber = 1
notification.soundName = UILocalNotificationDefaultSoundName
notification.fireDate = NSDate(timeIntervalSinceNow: 5)
print("Notification scheduled")
notification.userInfo = ["title": "Test", "UUID": "1"]
notification.repeatInterval = NSCalendarUnit.WeekOfMonth
UIApplication.sharedApplication().scheduleLocalNotification(notification)
I'm aware that when the app is in foreground there should be an event in didReceiveLocalNotification. I do not get an event in the appdelegate's didReceiveLocalNotification or the notification. However, when I use presentLocalNotificationNow with the notification - I the didReceiveLocalNotification in app delegate does get called. I also tried with other fireDates but it doesn't work. What am I missing?
Oh and I do have the below code in my appdelegate didfinishlaunchingapplication
let application = UIApplication.sharedApplication()
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
I had been testing, and this are my results, the problem seems to be related with time unit weekOfMonth with day works as intended, here is the picture of console log, using XCode 8.2, device iOS 10.2, still working
func scheduleTestNotification()
{
let notification = UILocalNotification()
notification.alertBody = "Reminder" // text that will be displayed in the notification
notification.alertAction = "open"
notification.applicationIconBadgeNumber = 1
notification.soundName = UILocalNotificationDefaultSoundName
notification.timeZone = NSTimeZone.default
notification.fireDate = Date(timeIntervalSinceNow: 5)
print("Notification scheduled")
notification.userInfo = ["title": "Test", "UUID": "1"]
notification.repeatInterval = NSCalendar.Unit.day
UIApplication.shared.scheduleLocalNotification(notification)
debugPrint(UIApplication.shared.scheduledLocalNotifications!)
}
but if I use weekOfMonth then
I think you can use this code as a workaround, it's not the best solution, but maybe can help you to achieve what you need
func scheduleTestNotification()
{
let notification = UILocalNotification()
notification.alertBody = "Reminder" // text that will be displayed in the notification
notification.alertAction = "open"
notification.applicationIconBadgeNumber = 1
notification.soundName = UILocalNotificationDefaultSoundName
notification.timeZone = NSTimeZone.default
notification.fireDate = Date(timeIntervalSinceNow: 5)
print("Notification scheduled")
notification.userInfo = ["title": "Test", "UUID": "1"]
UIApplication.shared.scheduleLocalNotification(notification)
notification.repeatInterval = NSCalendar.Unit.day
notification.fireDate = Calendar.current.date(byAdding: .day, value: 7, to: notification.fireDate!)
UIApplication.shared.scheduleLocalNotification(notification)
debugPrint(UIApplication.shared.scheduledLocalNotifications!)
}
I hope this helps you
To send notification in iOS 10 you need to ask permission as bellow before you fire the notification.
func requestPermition() {
let center = UNUserNotificationCenter.current()
center.getNotificationSettings { (settings) in
if settings.authorizationStatus != .authorized {
let options: UNAuthorizationOptions = [.alert, .sound];
center.requestAuthorization(options: options) {
(granted, error) in
if !granted {
print("Something went wrong")
}else {
print("permition granted")
}
}
}
}
}
UILocalNotification is deprecated in iOS 10 you may use UNUserNotificationCenter instead.to fire a notification try bellow code
//to fire notification after 5 seconds.
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5,
repeats: false)
//Set contents to be desplayed on the notification
let content = UNMutableNotificationContent()
content.title = "Reminder"
content.body = "Test reminder"
content.sound = UNNotificationSound.default()
content.categoryIdentifier = "myCategory"
let request = UNNotificationRequest(identifier: "textNotification", content: content, trigger: trigger)
//set UNNotificationActionOptions .foreground if you need to open when button tapped.
let action = UNNotificationAction(identifier: "remindOpen", title: "Open", options: [.foreground])
let category = UNNotificationCategory(identifier: "myCategory", actions: [action], intentIdentifiers: [], options: [])
UNUserNotificationCenter.current().setNotificationCategories([category])
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
UNUserNotificationCenter.current().add(request) {(error) in
if let error = error {
print("notification error: \(error)")
}
}
I tested and this code works on my side, iOS 10 with XCode 8.2
let settings = UIUserNotificationSettings(types: [.badge, .sound, .alert ], categories: nil)
UIApplication.shared.registerUserNotificationSettings(settings)
let notification = UILocalNotification()
notification.alertBody = "Reminder" // text that will be displayed in the notification
notification.alertAction = "open"
notification.applicationIconBadgeNumber = 1
notification.soundName = UILocalNotificationDefaultSoundName
notification.fireDate = Date(timeIntervalSinceNow: 5)
print("Notification scheduled")
notification.userInfo = ["title": "Test", "UUID": "1"]
notification.repeatInterval = NSCalendar.Unit.minute
UIApplication.shared.cancelAllLocalNotifications()
UIApplication.shared.scheduleLocalNotification(notification)
The method didReceiveNotification is called whenever the app pushes a local notification. My repeatInterval is minute instead of weekOfMonth. I think weekOfMonth is the problem because when I change repeatInterval to weekOfMonth, I did not receive notifications, the method didReceiveNotification never called.
So I also encountered a same problem.
I was trying to fire UILocalNotification from background fetch. I had UILocalNotification scheduled, I stepped through in Xcode, make sure that scheduleLocalNotification was called, but it only fired about 1/5 times.
It seems that scheduling UINotification from background fetch simply does not work reliably in iOS 10. I switched to using UNUserNotification and it fires reliably, every time I step through the code.

Actions buttons not showing up in local notifications ios 9.2 swift 2

I am creating notifications in a loop, relevant code is:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
appDelegate = self
serNotificationType = UIUserNotificationType.Alert.union(UIUserNotificationType.Sound).union(UIUserNotificationType.Badge)
let completeAction = UIMutableUserNotificationAction()
completeAction.identifier = "COMPLETE" // the unique identifier for this action
completeAction.title = "Clear" // title for the action button
completeAction.activationMode = .Background // UIUserNotificationActivationMode.Background - don't bring app to foreground
completeAction.authenticationRequired = false // don't require unlocking before performing action
completeAction.destructive = true // display action in red
let callInAction = UIMutableUserNotificationAction()
callInAction.identifier = "CALLIN"
callInAction.title = "Call now"
callInAction.destructive = false
callInAction.authenticationRequired = false
callInAction.activationMode = UIUserNotificationActivationMode.Background
callInAction.destructive = false
let notificationCategory = UIMutableUserNotificationCategory() // notification categories allow us to create groups of actions that we can associate with a notification
notificationCategory.identifier = "CALLINNOTIFICATION"
notificationCategory.setActions([callInAction, completeAction], forContext: .Default) //UIUserNotificationActionContext.Default (4 actions max)
notificationCategory.setActions([completeAction, callInAction], forContext: .Minimal) //UIUserNotificationActionContext.Minimal - for when space is limited (2 actions max)
application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: notificationTypes, categories: NSSet(array:[notificationCategory]) as? Set<UIUserNotificationCategory>))
return true
}
Scheduling of the notifications is done in the for loop (and maybe this is the reason something is wrong with scheduling):
func scheduleLocalNotifications() {
let arrayOfEvents: [[Meeting]] = CalendarController.sharedInstance.getAllMeetings()
//remove CallIn notifications anyway
self.removeScheduledNotifications()
var limitCounter = 0 //limit is 64 local notifications
print("scheduling start: \(CallIn.Settings.notifyNumberOfMinutesBeforeEvent)")
for var x = 0; x < arrayOfEvents.count; x++ {
for var y = 0; y < arrayOfEvents[x].count; y++ {
let event = arrayOfEvents[x][y]
if(event.startTime.timeIntervalSinceDate(NSDate()) > -2000 && limitCounter <= 64){
if(notificationsAreAllowed()){
let notification = UILocalNotification()
let minutesBefore = CallIn.Settings.notifyNumberOfMinutesBeforeEvent
notification.fireDate = event.startTime.dateByAddingTimeInterval(-minutesBefore * 60) //time of launch of notification
if(minutesBefore <= 1){
notification.alertBody = "Your \(event.title) is about to start"
}else{
notification.alertBody = "You have \(event.title) in \(Int(minutesBefore)) minutes"
}
notification.alertAction = "OK"
notification.soundName = UILocalNotificationDefaultSoundName
notification.userInfo = ["title": event.title, "UUID": event.UUID, "CallIn": "CallInNotification"]
notification.category = "CALLINNOTIFICATION"
notification.applicationIconBadgeNumber = 1
UIApplication.sharedApplication().scheduleLocalNotification(notification)
}
limitCounter += 1
}
}
}
}
The buttons Call now, and Dismiss are not showing up.
What I want is this:
What I get is this:
Ok, I found the problem and this may be useful for someone in the future:
I had
UIApplication.sharedApplication().registerUserNotificationSettings(notificationSettings)
was called twice in two different places in the application (because I had setting in the application, and needed to alter it from settings page).
So when refactored, and called it once, it worked.

Localnotification shows only two Actions?

I want to fire a simple local notification and display three actions. I followed different tutorials (e.g. https://gist.github.com/kristopherjohnson/06bab43acbd9cebe5fd7 or https://github.com/ariok/TB_InteractiveNotifications/blob/master/TB_InteractiveNotifications/AppDelegate.swift) and they all work (= fire the notification).
However, the lock screen only displays two actions no matter what I do (the tutorials all have three actions). I even commented out the minimal context (where only two actions are displayed).
I tried the iphone 4s, 5 and 6(s) simulator but they all have the same result.
Can anyone point me in the right direction?
ViewController.swift:
var categoryID:String {
get{
return "COUNTER_CATEGORY"
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let notification = UILocalNotification()
notification.alertBody = "Hey! Update your counter ;)"
notification.soundName = UILocalNotificationDefaultSoundName
notification.fireDate = NSDate(timeIntervalSinceNow: 5)
notification.category = categoryID
UIApplication.sharedApplication().scheduleLocalNotification(notification)
}
Appdelegate.swift:
enum Actions:String{
case increment = "INCREMENT_ACTION"
case decrement = "DECREMENT_ACTION"
case reset = "RESET_ACTION"
}
var categoryID:String {
get{
return "COUNTER_CATEGORY"
}
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
// 1. Create the actions **************************************************
// increment Action
let incrementAction = UIMutableUserNotificationAction()
incrementAction.identifier = Actions.increment.rawValue
incrementAction.title = "ADD +1!"
incrementAction.activationMode = UIUserNotificationActivationMode.Background
incrementAction.authenticationRequired = true
incrementAction.destructive = false
// decrement Action
let decrementAction = UIMutableUserNotificationAction()
decrementAction.identifier = Actions.decrement.rawValue
decrementAction.title = "SUB -1"
decrementAction.activationMode = UIUserNotificationActivationMode.Background
decrementAction.authenticationRequired = true
decrementAction.destructive = false
// reset Action
let resetAction = UIMutableUserNotificationAction()
resetAction.identifier = Actions.reset.rawValue
resetAction.title = "RESET"
resetAction.activationMode = UIUserNotificationActivationMode.Foreground
// NOT USED resetAction.authenticationRequired = true
resetAction.destructive = true
// 2. Create the category ***********************************************
// Category
let counterCategory = UIMutableUserNotificationCategory()
counterCategory.identifier = categoryID
// A. Set actions for the default context
counterCategory.setActions([incrementAction, decrementAction, resetAction],
forContext: UIUserNotificationActionContext.Default)
// 3. Notification Registration *****************************************
let types = UIUserNotificationType.Alert
let settings = UIUserNotificationSettings(forTypes: types, categories: NSSet(object: counterCategory) as? Set<UIUserNotificationCategory>)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
return true
}
Source: https://github.com/ariok/TB_InteractiveNotifications/blob/master/TB_InteractiveNotifications/AppDelegate.swift

How can I add action buttons/actions to UILocalNotification alert?

I have a local notification scheduled in my app, and right now I get a generic cancel (cross) button as I swipe the alert to the left.
I'm curious if I can add custom buttons/actions to it like on the image below?
I prepared for you some snipped code which shows notification with one button 10 second after ViewDidLoad method did shown.
import UIKit
class TestViewController: UIViewController {
let category = UIMutableUserNotificationCategory()
override func viewDidLoad() {
super.viewDidLoad()
let restartAction = UIMutableUserNotificationAction()
restartAction.identifier = "xx"
restartAction.destructive = false
restartAction.title = "Restart"
restartAction.activationMode = .Background
restartAction.authenticationRequired = false
let categoryIdentifier = "category.identifier"
category.identifier = categoryIdentifier
category.setActions([restartAction], forContext: .Minimal)
category.setActions([restartAction], forContext: .Default)
let categories = Set(arrayLiteral: category)
let settings = UIUserNotificationSettings(forTypes: [.Alert, .Sound], categories: categories)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
let localNotif = UILocalNotification()
localNotif.alertBody = "testBody"
localNotif.category = categoryIdentifier
// Notification will be shown after 10 second (IMPORTANT: if you want to see notification you have to close or put app into background)
localNotif.fireDate = NSDate().dateByAddingTimeInterval(10)
UIApplication.sharedApplication().scheduleLocalNotification(localNotif)
}
}
Note: you have to handle action in AppDelegate method:
func application(application: UIApplication, handleActionWithIdentifier identifier: String?,
forLocalNotification notification: UILocalNotification, completionHandler: () -> Void) {
completionHandler()
}
Of course my code is not as clean as it should be, but you have to know that I wrote it only for presentation purposes.
This code is written in Swift but convertion to Objective C should be very simple.

How to set a local notification to fire from a date stored in an array?

Im making a remind app and the so far the user is apple to successfully submit and store data from a form which is then stored in an array, this array writes to a file when the app is closed and then the data is loaded from the file when the app is reopened.
I am having an issue because I'm wanting to set the notifications to remind the user to complete the task at a certain time and I am not able to recall the NSDate that is stored in my array. Also I want to make the app work so that the notification is repeated everyday.
Here is my TableViewController:
class MedicineTableViewController: UITableViewController {
//MARK Properties
var medicines = [Medicine]()
override func viewDidLoad() {
super.viewDidLoad()
//Notifications Setup
let reminderActionOkay = UIMutableUserNotificationAction()
reminderActionOkay.identifier = "Okay"
reminderActionOkay.title = "Okay"
reminderActionOkay.activationMode = UIUserNotificationActivationMode.Background
reminderActionOkay.destructive = true
reminderActionOkay.authenticationRequired = false
let reminderActionOpen = UIMutableUserNotificationAction()
reminderActionOpen.identifier = "Open App"
reminderActionOpen.title = "Open App"
reminderActionOpen.activationMode = UIUserNotificationActivationMode.Background
reminderActionOpen.destructive = false
reminderActionOpen.authenticationRequired = true
//Put the different types of notifications into a category
let ReminderCategory = UIMutableUserNotificationCategory()
ReminderCategory.identifier = "reminderCategory"
ReminderCategory.setActions([reminderActionOpen, reminderActionOkay], forContext: UIUserNotificationActionContext.Default)
ReminderCategory.setActions([reminderActionOpen, reminderActionOkay], forContext: UIUserNotificationActionContext.Minimal)
//MARK: Notification Schedule
func scheduleLocalNotification() {
let localNotificationtime1 = UILocalNotification()
localNotificationtime1.alertTitle = "Take", medicines.name
localNotificationtime1.alertBody = "It is time to take", medicines.name
localNotificationtime1.alertAction = "Show Details"
localNotificationtime1.fireDate = medicine.time1 // 1 Day repeating
localNotificationtime1.timeZone = NSTimeZone.defaultTimeZone()
localNotificationtime1.soundName = UILocalNotificationDefaultSoundName
localNotificationtime1.applicationIconBadgeNumber = 1
localNotificationtime1.category = "reminderCategory"
UIApplication.sharedApplication().scheduleLocalNotification(localNotificationtime1)
let localNotificationtime2 = UILocalNotification()
localNotificationtime2.alertTitle = "Take", medicines.name
localNotificationtime2.alertBody = "It is time to take", medicines.name
localNotificationtime2.alertAction = "Show Details"
localNotificationtime2.fireDate = medicines.time2
localNotificationtime2.timeZone = NSTimeZone.defaultTimeZone()
localNotificationtime2.soundName = UILocalNotificationDefaultSoundName
localNotificationtime2.applicationIconBadgeNumber = 1
localNotificationtime2.category = "reminderCategory"
UIApplication.sharedApplication().scheduleLocalNotification(localNotificationtime2)
let localNotificationtime3 = UILocalNotification()
localNotificationtime3.alertTitle = "Take", medicines.name
localNotificationtime3.alertBody = "It is time to take", medicines.name
localNotificationtime3.alertAction = "Show Details"
localNotificationtime3.fireDate = medicines.time3
localNotificationtime3.timeZone = NSTimeZone.defaultTimeZone()
localNotificationtime3.soundName = UILocalNotificationDefaultSoundName
localNotificationtime3.applicationIconBadgeNumber = 1
localNotificationtime3.category = "reminderCategory"
UIApplication.sharedApplication().scheduleLocalNotification(localNotificationtime3)
let localNotificationtime4 = UILocalNotification()
localNotificationtime4.alertTitle = "Take", medicines.name
localNotificationtime4.alertBody = "It is time to take", medicines.name
localNotificationtime4.alertAction = "Show Details"
localNotificationtime4.fireDate = medicines.time4
localNotificationtime4.timeZone = NSTimeZone.defaultTimeZone()
localNotificationtime4.soundName = UILocalNotificationDefaultSoundName
localNotificationtime4.applicationIconBadgeNumber = 1
localNotificationtime4.category = "reminderCategory"
UIApplication.sharedApplication().scheduleLocalNotification(localNotificationtime4)
let localNotificationtime5 = UILocalNotification()
localNotificationtime5.alertTitle = "Take", medicines.name
localNotificationtime5.alertBody = "It is time to take", medicines.name
localNotificationtime5.alertAction = "Show Details"
localNotificationtime5.fireDate = medicines.time5
localNotificationtime5.timeZone = NSTimeZone.defaultTimeZone()
localNotificationtime5.soundName = UILocalNotificationDefaultSoundName
localNotificationtime5.applicationIconBadgeNumber = 1
localNotificationtime5.category = "reminderCategory"
UIApplication.sharedApplication().scheduleLocalNotification(localNotificationtime5)
}
}
Here is my AppDelegate:
import UIKit
import CoreData
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge], categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
// Override point for customization after application launch.
return true
}
func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
// Point for handling the local notification when the app is open.
// Showing reminder details in an alertview
UIAlertView(title: notification.alertTitle, message: notification.alertBody, delegate: nil, cancelButtonTitle: "OK").show()
}
func application(application: UIApplication, handleActionWithIdentifier identifier: String?, forLocalNotification notification: UILocalNotification, completionHandler: () -> Void) {
// Point for handling the local notification Action. Provided alongside creating the notification.
if identifier == "ShowDetails" {
// Showing reminder details in an alertview
UIAlertView(title: notification.alertTitle, message: notification.alertBody, delegate: nil, cancelButtonTitle: "OK").show()
} else if identifier == "Okay" {
} else if identifier == "Open App" {
//Launches app when open app button pressed
UIApplicationState.Active
}
completionHandler()
}
Here is my data model:
import UIKit
class Medicine : NSObject, NSCoding {
var name: String
var time1: NSDate
var time2: NSDate
var time3: NSDate
var time4: NSDate
var time5: NSDate
init?(name: String, time1: NSDate, time2: NSDate, time3: NSDate, time4: NSDate, time5: NSDate) {
self.name = name
self.time1 = time1
self.time2 = time2
self.time3 = time3
self.time4 = time4
self.time5 = time5
super.init()
if name.isEmpty {
return nil
}
}
I am also getting an error for the alert body and title since I don't know how I chain together the string followed by the stored information in the array.
Btw this is my first swift project since learning the language from scratch so go easy on me if I'm being an idiot. :(
Change these lines
localNotificationtime1.alertTitle = "Take", medicines.name
localNotificationtime1.alertBody = "It is time to take", medicines.name
to these
localNotificationtime1.alertTitle = "Take \(medicines.name)"
localNotificationtime1.alertBody = "It is time to take \(medicines.name)"
To add the time, add this code
localNotificationtime1.fireDate = NSDate(time1)

Resources