I am trying to create a local notification for my app using Apple's UNUserNotificationCenter.
Here is my code:
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = task.name
content.body = task.notes
content.sound = UNNotificationSound.default()
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
let request = UNNotificationRequest(identifier: task.UUID, content: content, trigger: trigger)
center.add(request) { (error:Error?) in
if let theError = error {
print("Notification scheduling error: \(error)")
}else{
print("Notification was scheduled successfully")
}
}
Access Request:
let center = UNUserNotificationCenter.current()
//request notification access
let options: UNAuthorizationOptions = [.alert, .sound]
center.requestAuthorization(options: options) { (granted, error) in
if !granted {
print("Notification access was denied")
}
}
After 5 seconds the app makes the Default sound but does not show the alert content. I am trying both with the app in the foreground and in the background.
I had the same problem.
If your content body is blank ie(content.body == "") then you won't get a notification even if you do have a title.
So the solution is to make sure that your content body is not an empty string.
Add this Protocoal UNUserNotificationCenterDelegate.
and add this delegate into your controller. and dont forget to set delegate.
UNUserNotificationCenter.current().delegate = self
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
print("Notification being triggered")
//You can either present alert ,sound or increase badge while the app is in foreground too with ios 10
//to distinguish between notifications
if notification.request.identifier == "yourrequestid"{
completionHandler( [.alert,.sound,.badge])
}
}
Add this code into didFinishLaunchingWithOption in AppDelegate.swift file
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound])
{ (granted, error) in
// Enable or disable features based on authorization.
}
Related
I added this code to my first ViewController
// Step-1 Ask permission from User
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.badge,.sound,.alert]) { granted, error in
if error == nil {
print("User permission is granted : \(granted)")
}
}
// Step-2 Create the notification content
let content = UNMutableNotificationContent()
content.title = "Hello"
content.body = "Welcome"
// Step-3 Create the notification trigger
let date = Date().addingTimeInterval(1)
let dateComponent = Calendar.current.dateComponents([.year,.month,.day,.hour,.minute,.second], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponent, repeats: false)
// Step-4 Create a request
let uuid = UUID().uuidString
let request = UNNotificationRequest(identifier: uuid, content: content, trigger: trigger)
// Step-5 Register with Notification Center
center.add(request) { error in
but 5 seconds pass without any notification shown. What is wrong? Could somebody show me how to fix it??
The notification comes but when the app is foreground it won't show until you implement UNUserNotificationCenterDelegate method
UNUserNotificationCenter.current().delegate = self
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.sound,.alert])
}
Also set
let date = Date().addingTimeInterval(5)
to give it some time until app hits so you can test it after clicking home button
import UIKit
class ViewController: UIViewController , UNUserNotificationCenterDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: [.badge,.sound,.alert]) { granted, error in
if error == nil {
print("User permission is granted : \(granted)")
}
}
// Step-2 Create the notification content
let content = UNMutableNotificationContent()
content.title = "Hello"
content.body = "Welcome"
// Step-3 Create the notification trigger
let date = Date().addingTimeInterval(5)
let dateComponent = Calendar.current.dateComponents([.year,.month,.day,.hour,.minute,.second], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponent, repeats: false)
// Step-4 Create a request
let uuid = UUID().uuidString
let request = UNNotificationRequest(identifier: uuid, content: content, trigger: trigger)
// Step-5 Register with Notification Center
center.add(request) { error in
}
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.sound,.alert])
}
}
I recently just finished an app that basically has an Observer for a Firebase Database, and when a certain attribute changes, sends a banner type notification.
The application works completely, but when I had the app in the background while using the phone, I realized that it doesn't run any code, or send notifications.
How can I implement both having the Observer listening for any changes from the Database in the background, as well as send a notification?
Here is the Notification Authorization Request function:
func requestNotificationAuthorization() {
let authOptions = UNAuthorizationOptions.init(arrayLiteral: .alert, .badge, .sound)
self.userNotificationCenter.requestAuthorization(options: authOptions) { (success, error) in
if let error = error {
print("Error: ", error)
}}}
The Notification Center function:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
completionHandler()
}
And the Send Notification function:
func sendNotification() {
// Create new notifcation content instance
let notificationContent = UNMutableNotificationContent()
// Add the content to the notification content
notificationContent.title = "P2P Tracker"
notificationContent.body = (PriceTimeDate ?? "")
print(notificationContent.body)
notificationContent.badge = NSNumber(value: 1)
// Add an attachment to the notification content
if let url = Bundle.main.url(forResource: "dune",
withExtension: "png") {
if let attachment = try? UNNotificationAttachment(identifier: "dune",
url: url,
options: nil) {
notificationContent.attachments = [attachment]
}
}
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 3,
repeats: false)
let request = UNNotificationRequest(identifier: "testNotification",
content: notificationContent,
trigger: trigger)
userNotificationCenter.add(request) { (error) in
if let error = error {
print("Notification Error: ", error)
}
}
}
I'm trying to implement local notifications within my app. The idea is that the user is sent a notification every day at 9:00 a.m. with a different quote, but I encountered a bug where the same content of the notification is always shown, i.e. the same quote is repeated endlessly. How could I fix it? This is the code I'm using, and I tried to use a UUID for every notification that is sent, but it didn't bring improvements.
let notificationCenter = UNUserNotificationCenter.current()
let options: UNAuthorizationOptions = [.alert, .sound]
notificationCenter.requestAuthorization(options: options) {
(didAllow, error) in
if !didAllow {
print("User has declined notifications")
}
}
notificationCenter.getNotificationSettings { (settings) in
if settings.authorizationStatus != .authorized {
print("Notifications not allowed")
}
}
let randomArrayNotificationQuote = Int(arc4random_uniform(UInt32(myQuotes.count)))
let randomArrayNotificationTitle = Int(arc4random_uniform(UInt32(myTitle.count)))
let content = UNMutableNotificationContent()
content.title = "\(myTitle[randomArrayNotificationTitle])"
content.body = "\(myQuotes[randomArrayNotificationQuote])"
content.sound = UNNotificationSound.default
content.categoryIdentifier = "com.giovannifilippini.philo"
// Deliver the notification
var dateComponents = DateComponents()
dateComponents.hour = 9
dateComponents.minute = 00
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let uuid = UUID().uuidString
let request = UNNotificationRequest.init(identifier: uuid, content: content, trigger: trigger)
notificationCenter.add(request) { (error) in
if error != nil {
print("add NotificationRequest succeeded!")
notificationCenter.removePendingNotificationRequests(withIdentifiers: [uuid])
}
}
The issue here is the trigger has the repeats set to true
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
You would need to set it to false and re run this method every time you want to schedule different notification (different content)
In order to receive the Notification while the app is in the foreground you need to implement the willPresent method from the UNUserNotificationCenterDelegate
Here is a simple example:
class ViewController: UIViewController {
private let userNotificaionCenter = UNUserNotificationCenter.current()
override func viewDidLoad() {
super.viewDidLoad()
// 1. Assign the delegate
userNotificaionCenter.delegate = self
scheduleNotification()
}
func scheduleNotification() {
// Same notification logic that you have
}
}
// 2. Implement the UNUserNotificationCenterDelegate
extension ViewController: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
// This will allow the app to receive alerts and sound while in the foreground
completionHandler([.alert, .sound])
}
}
I've set up notifications with UNUserNotificationCenter but they're only displayed when the app isn't running. There's some older threads asking the same question but the answers to those aren't working for me so I'm wondering if there's an updated way to do it.
The below code triggers local notification when app is in foreground and background.
import UIKit
import UserNotifications
class ViewController: UIViewController, UNUserNotificationCenterDelegate {
override func viewDidLoad() {
super.viewDidLoad()
//requesting for authorization
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge], completionHandler: {didAllow, error in
if error == nil {
self.triggerLocalNotification()
}
})
}
func triggerLocalNotification(){
//creating the notification content
let content = UNMutableNotificationContent()
//adding title, subtitle, body and badge
content.title = "Notification title "
content.subtitle = "Notification sub-title "
content.body = "We are learning about iOS Local Notification"
content.badge = 1
//it will be called after 5 seconds
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
//getting the notification request
let request = UNNotificationRequest(identifier: "SimplifiedIOSNotification", content: content, trigger: trigger)
UNUserNotificationCenter.current().delegate = self
//adding the notification to notification center
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
//displaying the ios local notification when app is in foreground
completionHandler([.alert, .badge, .sound])
}
}
I am trying to send a notification on a button click. This is the code in my viewController:
#IBAction func getNotificationButtonPressed(_ sender: Any) {
let content = UNMutableNotificationContent()
content.title = "Title"
content.body = "Body"
content.categoryIdentifier = "ident"
content.sound = UNNotificationSound.default()
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.1, repeats: false)
let request = UNNotificationRequest(identifier: "ident", content: content, trigger: trigger)
let center = UNUserNotificationCenter.current()
center.add(request) { (error : Error?) in
if let theError = error {
print(theError.localizedDescription)
} else {
print ("success")
}
}
}
also in AppDelegate I have requested permission to use Notifications:
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
// Enable or disable features based on authorization.
}
application.registerForRemoteNotifications()
P.S. I have imported
import UserNotifications
in both AppDelegate and the custom ViewController.
When you create notification at that check
if #available(iOS 10.0, *) {
let content = UNMutableNotificationContent()
content.title = "Intro to Notifications"
content.subtitle = "Lets code,Talk is cheap"
content.body = "Sample code from WWDC"
content.sound = UNNotificationSound.default()
// Deliver the notification in five seconds.
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 5.0, repeats: false)
let request = UNNotificationRequest(identifier:requestIdentifier, content: content, trigger: trigger)
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().add(request){(error) in
if (error != nil){
print(error?.localizedDescription)
}
}
}
Implement this delegates method UNUserNotification for Notification being triggered.
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print("Tapped in notification")
}
//This is key callback to present notification while the app is in foreground
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
print("Notification being triggered")
//You can either present alert ,sound or increase badge while the app is in foreground too with ios 10
//to distinguish between notifications
if notification.request.identifier == requestIdentifier{
completionHandler( [.alert,.sound,.badge])
}
}
Happy coding.