Hello I want to add a button action to my UNMutableNotification but I do not understand why it does not work, yet I passed him the catergoryIdentifier.
My code:
class LocalNotification: NSObject {
class func createToDate(identifier: String,
title: String,
subtitle: String = "",
body: String,
to date: Date,
sound: UNNotificationSound = .default,
repeatNotification: Bool = false,
completion: #escaping (_ error: Error?) -> ()) {
let content = UNMutableNotificationContent()
content.title = title
content.subtitle = subtitle
content.body = body
content.sound = sound
content.categoryIdentifier = "fittoCateroy"
let dateComponent = Calendar.current.dateComponents([.day, .hour, .minute], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponent, repeats: repeatNotification)
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { (error) in
completion(error)
}
}
class func withAction() {
let snoozeAction = UNNotificationAction(identifier: "snooze", title: "Snooze", options: [])
let category = UNNotificationCategory(identifier: "fittoCateroy", actions: [snoozeAction], intentIdentifiers: [], options: [])
UNUserNotificationCenter.current().setNotificationCategories([category])
createToDate(identifier: "M",
title: "My title", subtitle: "Sub", body: "Body",
to:Date().adding(seconds: 10), sound: .default, repeatNotification: false) { error in
if let error = error {
print("ERRRRROR \(error.localizedDescription)")
}
}
}
}
When I call from my controller the function createToDate() the notification work, but if I call the function withAction(), the notification does not work.
The Date().adding(second: 10) is a custom extension
Related
My problem is that I am trying to schedule notifications that come daily at a specific time this is my code
import SwiftUI
struct notifView: View {
var body: some View {
VStack {
VStack {
Button("Request Permission") {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
if granted {
print("Access Granted!")
} else {
print("Access Not Granted")
}
}
}
.frame(width: 200, height: 60, alignment: .center)
.foregroundColor(.black)
.background(Color.blue)
.cornerRadius(10.0)
.padding()
Button("Add Notifications For Morning") {
func scheduleNotification() {
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = "Morning Time"
content.body = "Wake Up And Be Productive!"
content.categoryIdentifier = "reminder"
content.sound = UNNotificationSound.default
var dateComponents = DateComponents()
dateComponents.hour = 6
dateComponents.minute = 30
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
center.add(request)
}
}
.padding()
Button("Add Notifications For Middle Of The Day") {
func scheduleNotification() {
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = "Middle Of The Day"
content.body = "Did you have your daily run?"
content.categoryIdentifier = "reminder"
content.sound = UNNotificationSound.default
var dateComponents = DateComponents()
dateComponents.hour = 12
dateComponents.minute = 30
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
center.add(request)
}
}
.padding()
Button("Add Notifications For Night") {
func scheduleNotification() {
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = "Night Time"
content.body = "Time to sleep"
content.categoryIdentifier = "reminder"
content.sound = UNNotificationSound.default
var dateComponents = DateComponents()
dateComponents.hour = 20
dateComponents.minute = 51
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
center.add(request)
}
}
.foregroundColor(.blue)
.padding()
}
}
}
}
struct notifView_Previews: PreviewProvider {
static var previews: some View {
notifView()
}
}
Look at the comments within the code
import SwiftUI
//struct and class should start with an uppercase
struct NotificationView: View {
//Central location for Notification code including the delegate
// A call to the notificationManager just like the line of code below has to be included in
// application(_:willFinishLaunchingWithOptions:) or
// application(_:didFinishLaunchingWithOptions:)
//https://developer.apple.com/documentation/usernotifications/unusernotificationcenterdelegate
//https://www.hackingwithswift.com/quick-start/swiftui/how-to-add-an-appdelegate-to-a-swiftui-app
let notificationManager: NotificationManager = NotificationManager.shared
var body: some View {
VStack {
VStack {
Button("Request Permission") {
//Call a func here don't define it
notificationManager.requestAuthorization()
}
.frame(width: 200, height: 60, alignment: .center)
.foregroundColor(.black)
.background(Color.blue)
.cornerRadius(10.0)
.padding()
Button("Add Notifications For Morning") {
//Unique date components
var dateComponents = DateComponents()
dateComponents.hour = 6
dateComponents.minute = 30
//Reusable method
self.notificationManager.scheduleTriggerNotification(title: "Morning Time", body: "Wake Up And Be Productive!", categoryIdentifier: "reminder", dateComponents: dateComponents, repeats: true)
}
.padding()
Button("Add Notifications For Middle Of The Day") {
var dateComponents = DateComponents()
dateComponents.hour = 12
dateComponents.minute = 30
//Reusable method
self.notificationManager.scheduleTriggerNotification(title: "Middle Of The Day", body: "Did you have your daily run?", categoryIdentifier: "reminder", dateComponents: dateComponents, repeats: true)
}
.padding()
Button("Add Notifications For Night") {
var dateComponents = DateComponents()
dateComponents.hour = 20
dateComponents.minute = 51
//Reusable method
self.notificationManager.scheduleTriggerNotification(title: "Night Time", body: "Time to sleep", categoryIdentifier: "reminder", dateComponents: dateComponents, repeats: true)
}
.foregroundColor(.blue)
.padding()
Button("Print Notifications") {
//Reusable method
self.notificationManager.printNotifications()
}
.foregroundColor(.blue)
.padding()
Button("Delete Notifications") {
//Reusable method
self.notificationManager.deleteNotifications()
}
.foregroundColor(.blue)
.padding()
}
}
}
}
//You need a central location for the notification code because
// it is needed in more than 1 spot. At launch in the AppDelegate
// and wherever you schedule your notifications
class NotificationManager: NSObject, UNUserNotificationCenterDelegate{
//Singleton is requierd because of delegate
static let shared: NotificationManager = NotificationManager()
let notificationCenter = UNUserNotificationCenter.current()
private override init(){
super.init()
//This assigns the delegate
notificationCenter.delegate = self
}
func requestAuthorization() {
print(#function)
notificationCenter.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
if granted {
print("Access Granted!")
} else {
print("Access Not Granted")
}
}
}
func deleteNotifications(){
print(#function)
notificationCenter.removeAllPendingNotificationRequests()
}
///This is just a reusable form of all the copy and paste you did in your buttons. If you have to copy and paste make it reusable.
func scheduleTriggerNotification(title: String, body: String, categoryIdentifier: String, dateComponents : DateComponents, repeats: Bool) {
print(#function)
let content = UNMutableNotificationContent()
content.title = title
content.body = body
content.categoryIdentifier = categoryIdentifier
content.sound = UNNotificationSound.default
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: repeats)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
notificationCenter.add(request)
}
///Prints to console schduled notifications
func printNotifications(){
print(#function)
notificationCenter.getPendingNotificationRequests { request in
for req in request{
if req.trigger is UNCalendarNotificationTrigger{
print((req.trigger as! UNCalendarNotificationTrigger).nextTriggerDate()?.description ?? "invalid next trigger date")
}
}
}
}
//MARK: UNUserNotificationCenterDelegate
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler(.banner)
}
}
struct NotificationView_Previews: PreviewProvider {
static var previews: some View {
NotificationView()
}
}
I got it working with the help of this video:
https://www.youtube.com/watch?v=mG9BVAs8AIo
and some code from #lorem ipsum thank you so much for the help
import SwiftUI
import UserNotifications
struct notifView: View {
var body: some View {
VStack {
Button("Request Permission") {
NotificationManager.instance.requestAuthorization()
}
.padding()
.background(Color.green)
.cornerRadius(10)
Button("1st Notification") {
var dateComponents = DateComponents()
dateComponents.hour = 4
dateComponents.minute = 01
// reusable code thanks to lorem ipsum
NotificationManager.instance.scheduleTriggerNotification(title: "1st Notification", body: "1st Notification Body", categoryIdentifier: UUID().uuidString, dateComponents: dateComponents, repeats: true)
}
.padding()
.background(Color.yellow)
.cornerRadius(10)
Button("2nd Notification") {
var dateComponents = DateComponents()
dateComponents.hour = 5
dateComponents.minute = 40
// reusable code thanks to lorem ipsum
NotificationManager.instance.scheduleTriggerNotification(title: "2nd Notification", body: "2nd Notification Body", categoryIdentifier: UUID().uuidString, dateComponents: dateComponents, repeats: true)
}
.padding()
.background(Color.yellow)
.cornerRadius(10)
Button("3rd Notification") {
var dateComponents = DateComponents()
dateComponents.hour = 12
dateComponents.minute = 10
// reusable code thanks to lorem ipsum
NotificationManager.instance.scheduleTriggerNotification(title: "3rd Notification", body: "3rd Notification Body", categoryIdentifier: UUID().uuidString, dateComponents: dateComponents, repeats: true)
}
.padding()
.background(Color.yellow)
.cornerRadius(10)
}
}
}
class NotificationManager {
static let instance = NotificationManager()
func requestAuthorization() {
let options: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: options) { (success, error) in
if let error = error {
print("ERROR: \(error)")
} else {
print("SUCCESS")
}
}
}
// reusable code thanks to lorem ipsum
func scheduleTriggerNotification(title: String, body: String, categoryIdentifier: String, dateComponents : DateComponents, repeats: Bool) {
print(#function)
let content = UNMutableNotificationContent()
content.title = title
content.body = body
content.categoryIdentifier = categoryIdentifier
content.sound = UNNotificationSound.default
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: repeats)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
notifView()
}
}
Add one day in today's date so we got next day and then add your specific time on which you want trigger the notification.
var triggerComponents = DateComponents()
let nextDay = Calendar.current.date(byAdding: .day, value: 1, to: Date()) ?? Date()
triggerComponents = Calendar.current.dateComponents([.year, .month, .day, .hour], from: nextDay)
triggerComponents.hour = 14
I would like to schedule a local notification from iOS14 widget.
How can I do it?
I tried implementing the following:
let center = UNUserNotificationCenter.current()
center.delegate = self
let content = UNMutableNotificationContent()
content.title = "Some Title"
content.body = "Some Body"
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString,
content: content, trigger: trigger)
center.add(request) { (error) in
if error != nil {
// Handle any errors.
}
I did with this.
func createDate(day: Int, month : Int, hour: Int, minute: Int, year: Int)->Date{
var components = DateComponents()
components.hour = hour
components.minute = minute
components.year = year
components.day = day
components.month = month
components.timeZone = .current
let calendar = Calendar(identifier: .gregorian)
return calendar.date(from: components)!
}
// 📢///CreateNitification
func scheduleNotification(at date: Date, identifierUnic : String, body: String, titles:String) {
let triggerWeekly = Calendar.current.dateComponents([.day, .month, .hour,.minute, .year], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerWeekly, repeats: true)
let content = UNMutableNotificationContent()
content.title = titles
content.body = body
content.sound = UNNotificationSound.default
content.categoryIdentifier = "todoList2"
let request = UNNotificationRequest(identifier: identifierUnic, content: content, trigger: trigger)
// UNUserNotificationCenter.current().delegate = self
/// UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: ["textNotification2"])
/// UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
UNUserNotificationCenter.current().add(request) {(error) in
if let error = error {
print(" We had an error: \(error)")
}}
}
// Call
func callNotifications(){
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
let adte = createDate(day: 3, month: 6, hour: 16, minute: 51, year: 2021)
scheduleNotification(at: adte, identifierUnic: UUID().uuidString, body: "Widgets on Work", titles: "check 123")
}
func getTimeline(in context: Context, completion: #escaping (Timeline<Entry>) -> ()) {
callNotifications()
var entries: [SimpleEntry] = []
// Generate a timeline consisting of five entries an hour apart, starting from the current date.
let currentDate = Date()
for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
let entry = SimpleEntry(date: entryDate)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
Notification is working fine
but one thing is pending, how can I call UNUserNotificationCenter.current().delegate = self?
Thanks
The bottom line is that I made one local notification for a time interval of 10 seconds.
How do I add multiple notifications to this code with different time delays? That is, different notifications with different delays (several hours, days, and so on).
If this is possible, please use the example of my code.
I was told that I need to put a different identifier: "content" and different times. But I don't understand what parts of the code I need to duplicate.
import UIkit
import UserNotifications
class ViewController UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = "Hi"
content.body = "Bear"
content.sound = UNNotificationSound.default
content.threadIdentifier = "local-notifications"
let date = Date(timeIntervalSinceNow: 10)
let dateComponents = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute, .second], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
let request = UNNotificationRequest(identifier: "content", content: content, trigger: trigger)
center.add(request) {(error) in
if error != nil {
print (error)
}
}
}
```
You can create method scheduleNotification(identifier:content:date:) in UNUserNotificationCenter extension ,
extension UNUserNotificationCenter {
func scheduleNotification(identifier: String, content: UNMutableNotificationContent, date: Date) {
let dateComponents = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute, .second], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
self.add(request) {(error) in
if error != nil {
print (error)
}
}
}
}
Now, call this method for multiple notifications with the appropriate parameters that you want to use, i.e.
Example-1:
let content1 = UNMutableNotificationContent()
content1.title = "Hi"
UNUserNotificationCenter.current().scheduleNotification(identifier: "content1", content: content1, date: Date(timeIntervalSinceNow: 10))
Example-2:
let content2 = UNMutableNotificationContent()
content2.title = "Hello"
UNUserNotificationCenter.current().scheduleNotification(identifier: "content2", content: content2, date: Date(timeIntervalSinceNow: 20))
UNLocationNotificationTrigger is not working.
Even ,CLLocationManager didEnterRegion() is working.
I have added both locationManager.startMonitoring(for:region) and locationManager.startUpdatingLocation()
Even I tried by removing locationManager.startUpdatingLocation().But not working
func startMonitoring(list:List) {
if !CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) {
return
}
self.list = list
let region = self.region(list: list)
self.locationBasedNotification(list: list, flag: true, region: region as! CLCircularRegion)
locationManager.startMonitoring(for:region)
locationManager.startUpdatingLocation()
}
func stopMonitoring(list:List) {
self.list = list
for region in locationManager.monitoredRegions {
let circularRegion = region as? CLCircularRegion
if circularRegion?.identifier == list.identifier {
self.locationBasedNotification(list: list, flag: false, region: circularRegion!)
locationManager.stopMonitoring(for: circularRegion!)
// monitoredRegions.removeValueForKey(region.identifier)
}
}
}
func locationBasedNotification(list:List,flag:Bool,region:CLCircularRegion) {
var trigger : UNLocationNotificationTrigger!
if flag == true {
self.locationIdentifier = "location"+String(list.seqNo)
let categoryIdentifier = "locationmyCategory"+String(list.seqNo)
let textIdentifier = "locationtext"+String(list.seqNo)
let action = UNNotificationAction(identifier: self.locationIdentifier!, title: "You, have entered \(list.storeName)", options: [])
let category = UNNotificationCategory(identifier: categoryIdentifier, actions: [action], intentIdentifiers: [], options: [])
UNUserNotificationCenter.current().setNotificationCategories([category])
trigger = UNLocationNotificationTrigger(region: region, repeats: true)
let content = UNMutableNotificationContent.init()
content.title = list.storeName
content.body = "They are \(list.totalItems) in Shopping List"
content.sound = UNNotificationSound.default()
content.categoryIdentifier = categoryIdentifier
let request = UNNotificationRequest(identifier: textIdentifier, content: content, trigger: trigger)
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().add(request) {(error) in
if let error = error {
print("Uh oh! We had an error: \(error)")
}
}
} else {
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: ["locationIdentifier"+String(list.seqNo)])
}
}
please provide me input on this
I'm trying to fix my notifications displaying every day what should I pack up for school for next day.
Everything seems ok, but content.subtitle shows error :
Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1007dbb00)
Is there problem with array also? I searched for answer, but it looks like nobody used array for notification body. Is it even possible?
And if it's not can I replace it with better replacement?
Thanks for any help.
let plan = [
["dzien": "Sunday", "lekcje": nil],
["dzien": "Saturday", "lekcje":["pon1","pon2","pon3"]],
["dzien": "Tuesday", "lekcje":["wt1","wt2","wt3"]],
["dzien": "Wednesday", "lekcje":["sr1","sr2","sr3"]],
["dzien": "Thursday", "lekcje":["cz1","cz2","cz3"]],
["dzien": "Friday", "lekcje":["pt1","pt2","pt3"]],
["dzien": "Saturday", "lekcje": nil],
]
func getDayOfWeek() -> Int {
let myCalendar = Calendar(identifier: .gregorian)
let weekDay = myCalendar.component(.weekday, from: Date())
return weekDay - 1
}
#objc func registerLocal() {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
if granted {
print("Sukces")
} else {
print("Nie dzieła")
}
}
}
#objc func scheduleLocal() {
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
let d = getDayOfWeek()%6
let dzis = plan[d]
if dzis["lekcje"] != nil {
content.title = "Pack up"
content.subtitle = dzis["dzien"]
var lekcje = ""
for lekcja in dzis["lekcje"] {
lekcje+="\(lekcja)\n"
}
content.body = lekcje
content.userInfo = ["customData": "fizzbuzz"]
} else {
content.title = "Tommorow \(dzis["dzien"]), You don't have any subjects."
}
var dateComponents = DateComponents()
dateComponents.hour = 16
dateComponents.minute = 00
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
center.add(request)
}
}
The problem is that the compiler infers the type of plans as [String:Any] and when you are trying to do content.subtitle = dzis["dzien"], dzis["dzien"] is of type Any and not String.
You have to cast it to String in order to work.
guard let subtitle = dzis["dzien"] as? String else {return}
content.subtitle = subtitle