Localnotification shows only two Actions? - ios

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

Related

How to make local notification actions directly delete To-Do Items in Swift

I have a Table View Controller project in Swift.
I would need 2 Local Notification actions: one to complete and delete a deadline to-do item, and the other one to open a View Controller of the app.
I have already added NSNotificationCenter.defaultCenter().addObserver for the actions but I'm still wondering how to delete the to-do items from the cellForRowAtIndexPath. using just the the notification actions.
I hope you could help me! Thank you in advance!
Here are some parts of my codes:
AppDelegate:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Actions
var firstAction:UIMutableUserNotificationAction = UIMutableUserNotificationAction()
firstAction.identifier = "FIRST_ACTION"
firstAction.title = "Complete" // "First Action"
firstAction.activationMode = UIUserNotificationActivationMode.Background
firstAction.destructive = true
firstAction.authenticationRequired = false
var secondAction:UIMutableUserNotificationAction = UIMutableUserNotificationAction()
secondAction.identifier = "SECOND_ACTION"
secondAction.title = "Edit" // "Second Action"
secondAction.activationMode = UIUserNotificationActivationMode.Foreground
secondAction.destructive = false
secondAction.authenticationRequired = false
var thirdAction:UIMutableUserNotificationAction = UIMutableUserNotificationAction()
thirdAction.identifier = "THIRD_ACTION"
thirdAction.title = "Third Action"
thirdAction.activationMode = UIUserNotificationActivationMode.Background
thirdAction.destructive = false
thirdAction.authenticationRequired = false
// category
var firstCategory:UIMutableUserNotificationCategory = UIMutableUserNotificationCategory()
firstCategory.identifier = "FIRST_CATEGORY"
let defaultActions:NSArray = [firstAction, secondAction, thirdAction]
let minimalActions:NSArray = [firstAction, secondAction]
firstCategory.setActions(defaultActions as! [UIUserNotificationAction], forContext: UIUserNotificationActionContext.Default)
firstCategory.setActions(minimalActions as! [UIUserNotificationAction], forContext: UIUserNotificationActionContext.Minimal)
// NSSet of all our categories
let categories:NSSet = NSSet(objects: firstCategory)
let types:UIUserNotificationType = UIUserNotificationType(arrayLiteral: .Alert, .Badge)
let mySettings:UIUserNotificationSettings = UIUserNotificationSettings(forTypes: types, categories: categories as! Set<UIUserNotificationCategory>)
UIApplication.sharedApplication().registerUserNotificationSettings(mySettings)
func application(application: UIApplication!,
handleActionWithIdentifier identifier:String!,
forLocalNotification notification:UILocalNotification!,
completionHandler: (() -> Void)!){
if (identifier == "First_Action"){
NSNotificationCenter.defaultCenter().postNotificationName("actionOnePressed", object: nil)
}else if (identifier == "Second_Action"){
NSNotificationCenter.defaultCenter().postNotificationName("actionTwoPressed", object: nil)
}
completionHandler()
ToDoTableViewController:
//
NSNotificationCenter.defaultCenter().addObserver(self, selector: "drawAShape", name: "actionOnePressed", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "showAMessage", name: "actionTwoPressed", object: nil)
//
let newIndexPath = NSIndexPath(forRow: todoItems.count, inSection: 0)
todoItems.append(todoItem)
tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Bottom)
//scheduleLocalNotification(todoItem)
let notification:UILocalNotification = UILocalNotification()
notification.category = "FIRST_CATEGORY"
notification.alertBody = "Notification \(todoItem.title)"
notification.fireDate = fixNotificationDate(todoItem.deadline)
notification.userInfo = ["note":todoItem.note, "title": todoItem.title]
UIApplication.sharedApplication().scheduleLocalNotification(notification)
At the moment you are not passing anything between application:handleActionWithIdentifier:forLocalNotification:completionHandler: and the functions to do something. Therefore those functions don't know what to do.
The identifier you pass needs to provide enough information to identify what to do. For example it might be "delete=123" to delete record 123. Then you would pass this in the postNotification:
NSNotificationCenter.defaultCenter().postNotificationName("actionTwoPressed",
object: nil, userInfo: identifier)
Now you want to pick it up in the handler for the actionTwoPressed notification, which for you is showAMessage, so it will need a parameter:
func showAMessage(notification: NSNotification) {
// notification.userInfo is the identifier
}
This also means you need to change the addObserver, including the ":" to show a parameter is passed:
NSNotificationCenter.defaultCenter().addObserver(self,
selector: "showAMessage", name: "actionTwoPressed:", object: nil)
Also, none of this code would be in cellForRowAtIndexPath.

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.

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)

iOS locale notification pop-up doesn't appear

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
}

Resources