I am trying to send a local notification. My Code is Below mentioned.
Problem Is that notification not fire. i tried all possible answered on stackoverflow. please suggest.
I clear all Notification on did finish launching and also set a user permission for the notification
func applicationWillTerminate(_ application: UIApplication) {
self.loadData()
for obj in eventArray
{
if (obj["notification"] as? Bool)!
{
scheduleNotification(obj["time"] as! Date, obj["title"] as! String)
print(obj["time"] as! Date)
}
}
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
func scheduleNotification(_ date: Date, _ title:String) {
let formatter = DateFormatter()
formatter.dateFormat = "HH"
let myhour = formatter.string(from: date)
let number = NumberFormatter()
let mynumberhour = number.number(from: myhour)
let intHour = mynumberhour?.intValue
print(intHour!)
formatter.dateFormat = "mm"
let myminute = formatter.string(from: date)
let mynumberMinute = number.number(from: myminute)
let intMinute = mynumberMinute?.intValue
print(intMinute!)
formatter.dateFormat = "MM"
let mymonth = formatter.string(from: date)
let mynumberMonth = number.number(from: mymonth)
let intMonth = mynumberMonth?.intValue
print(intMonth!)
formatter.dateFormat = "dd"
let myday = formatter.string(from: date)
let mynumberday = number.number(from: myday)
let intday = mynumberday?.intValue
print(intday!)
let calendar = Calendar.current
//let components = calendar.dateComponents(in: .current, from: date)
let newComponents = DateComponents(calendar: calendar, timeZone: .current, month: intMonth, day: intday, hour: intHour, minute: intMinute)
let trigger = UNCalendarNotificationTrigger(dateMatching: newComponents, repeats: true)
let content = UNMutableNotificationContent()
content.title = " Today's Event"
content.body = "Event Is Generated"
content.sound = UNNotificationSound.default()
let request = UNNotificationRequest(identifier: title, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) {(error) in
if let error = error {
print("Uh oh! We had an error: \(error)")
}
}
}
Problem I solved.
I called a "func scheduleNotification" in "func applicationDidEnterBackground" and notification fire properly.
Related
I am trying to set up local notifications that are triggered under two circumstances:
- An x number of days after the first use of the app
- In case the user has gone an x number of days without using the app
Is this possible? All the information I have found online is about setting notifications to go off at a specific time, but how can I send depending on the app's first and last use?
First of all, you need a request to register the notifications, and after the notification is granted, you can call the functions that firing the notifications on the specific time.
In AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let center = UNUserNotificationCenter.current()
let options: UNAuthorizationOptions = [.alert, .sound]
center.requestAuthorization(options: options, completionHandler: { granted, error in
if granted {
self.setNotificationForFirstTimeUseApp()
self.setNotificationForLastTimeUseApp()
print("Notification is granted")
} else {
print("Notification is not granted")
}
})
return true
}
Create the functions for firing the notification on a specific time:
func setNotificationForFirstTimeUseApp() {
// Check the app, if it is opened before
if let _ = UserDefaults.standard.value(forKey: "appOpened") as? Bool {
return
}
// Save a flag on preferences that it tells the app is opened for the first time
UserDefaults.standard.set(true, forKey: "appOpened")
let content = UNMutableNotificationContent()
content.title = "Using for the first time - Notification" // Add your own title
content.body = "Awesome thank you for using this application!" // Add your own description
content.sound = UNNotificationSound.default
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = NSTimeZone.local
// Specific the time you want to fire the notification (after some days, hours, minutes...)
if let date = Date.getDateByAdding(days: 0, hours: 0, minutes: 0, seconds: 5) {
let componentsForFireDate = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second, .timeZone], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: componentsForFireDate, repeats: false)
let identifier = "firstTimeUseApp"
let request = UNNotificationRequest(
identifier: identifier,
content: content,
trigger: trigger)
let center = UNUserNotificationCenter.current()
center.add(request, withCompletionHandler: { error in
if error != nil {
if let error = error {
print("Something went wrong: \(error)")
}
}
})
center.getPendingNotificationRequests(completionHandler: { requests in
print(String(format: "PendingNotificationRequests %i", requests.count))
for req in requests {
let trigger = req.trigger
if let trigger = trigger {
print("trigger \(trigger)")
}
}
})
}
}
func setNotificationForLastTimeUseApp () {
let content = UNMutableNotificationContent()
content.title = "Using for the last time - Notification" // Add your own title
content.body = "You have not used the application for a long time!" // Add your own description
content.sound = UNNotificationSound.default
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = NSTimeZone.local
// Specific the time you want to fire the notification (after some days, hours, minutes...)
if let date = Date.getDateByAdding(days: 0, hours: 0, minutes: 0, seconds: 10) {
let componentsForFireDate = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second, .timeZone], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: componentsForFireDate, repeats: false)
let identifier = "lastTimeUseApp"
let request = UNNotificationRequest(
identifier: identifier,
content: content,
trigger: trigger)
let center = UNUserNotificationCenter.current()
// Remove pending notifications
center.removePendingNotificationRequests(withIdentifiers: [identifier])
center.add(request, withCompletionHandler: { error in
if error != nil {
if let error = error {
print("Something went wrong: \(error)")
}
}
})
center.getPendingNotificationRequests(completionHandler: { requests in
print(String(format: "PendingNotificationRequests %i", requests.count))
for req in requests {
let trigger = req.trigger
if let trigger = trigger {
print("trigger \(trigger)")
}
}
})
}
}
And finally, add this function. It will calculate a future date by adding days, hours, minutes and seconds, from now.
extension Date {
static func getDateByAdding(days: Int, hours: Int, minutes: Int, seconds: Int) -> Date? {
let currentDate = Date()
var dateComponent = DateComponents()
dateComponent.day = days
dateComponent.hour = hours
dateComponent.minute = minutes
dateComponent.second = seconds
let futureDate = Calendar.current.date(byAdding: dateComponent, to: currentDate)
return futureDate
}
}
I hope this answer will help you with your issue!
hi I want to make a local notification from string time, I want the notification launch 10 minute before given time. I have trouble how to make the time from 4:01 into 3:51, please help. this is my code
let a = "4:01"
func startNoftification(prayer: String) {
let time = prayer.split(separator: ":").map { (x) -> Int in
return Int(String(x))!
}
let content = UNMutableNotificationContent()
content.title = "Adzan"
content.body = "it's time to sholat dzuhur"
let gregorian = Calendar(identifier: .gregorian)
var component = gregorian.dateComponents([.year, .month, .day, .hour, .minute, .second], from: Date())
component.hour = time[0]
component.minute = time[1] - 10
guard let date = gregorian.date(from: component) else { return }
let triggerDaily = Calendar.current.dateComponents([.hour, .minute, .second], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: true)
let request = UNNotificationRequest(identifier: "Hijrah", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { (error) in
if let err = error {
print("Notif error:", err)
return
}
}
}
Is this what you need?
let time = "4:01"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "hh:mm"
guard let date = dateFormatter.date(from: time) else {
return
}
let targetTime = Date(timeInterval: -(10 * 60), since: date) // Change time interval to required value in seconds
let targetTimeString = dateFormatter.string(from: targetTime)
print(targetTimeString) // Prints 3:51
Or if your countdown time has a lot of time components, use DateComponents.
var dateComponents = DateComponents()
dateComponents.minute = -10
// Other components
if let targetTime = Calendar.current.date(byAdding: dateComponents, to: date)
print(dateFormatter.string(from: targetTime))
}
Here I have solution combine with rakesha Shastri answer, hopefully it can helps others.
First import UserNotification in appDelegate and in your controller
import UserNotification
and add code for didFinishWithLaunchingWithOptions
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge]) { (granted, error) in
if let err = error {
print("Notifications permission denied because:", err)
return
}
if granted {
print("Notifications permission granted.")
}
}
}
and you can make a function and add string time parameters either from API or arbitrary string, since I'm not using function so I pass my solution in viewDidLoad
let adzan = "4:01"
let content = UNMutableNotificationContent()
content.title = "Adzan"
content.body = "It's time for sholat"
content.sound = UNNotificationSound.default
// Format the date first from string time
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
//addingTimeInterval is where you want to set notification before or after deciding time in this case I set it 10 minute before deciding time
guard let date = dateFormatter.date(from: adzan)?.addingTimeInterval(-600) else { return }
// and convert our date into dateComponents
let triggerDate = Calendar.current.dateComponents([.hour, .minute, .second], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)
In my application I can select date and time for EKEvent. I almost achieved what I want except Time. How can I set time. Below is my code, I have tried.
func setReminder(){
let eventStore = EKEventStore()
eventStore.requestAccess(
to: EKEntityType.event, completion: {(granted, error) in
if !granted {
print("Access to store not granted")
print(error!.localizedDescription)
} else {
print("Access granted")
let event = EKEvent(eventStore: eventStore)
event.title = self.getCategoryText + " Reminder"
event.calendar =
eventStore.defaultCalendarForNewEvents
event.timeZone = TimeZone.current
let alarm = EKAlarm(absoluteDate: self.selectedDate!)
event.addAlarm(alarm)
if self.daysBeforeDate != nil{
let earlierDate = self.daysBeforeDate
let earlierAlarm = EKAlarm(absoluteDate: earlierDate!)
event.addAlarm(earlierAlarm)
}
print("selected time", self.selectedTime)
var number1: Double = (self.selectedTime! as NSString).doubleValue
event.startDate = self.selectedDate!.addingTimeInterval(number1)
event.endDate = self.selectedDate!
do {
try eventStore.save(event, span: .thisEvent, commit: true)
} catch let error {
print("Reminder failed with error \(error.localizedDescription)")
return
}
}
})
}
Update 1
let calendar = Calendar.current
var dateComponents = DateComponents()
dateComponents.year = calendar.component(.year, from: self.selectedDate!)
dateComponents.month = calendar.component(.month, from: self.selectedDate!)
dateComponents.day = calendar.component(.day, from: self.selectedDate!)
dateComponents.timeZone = TimeZone.current
dateComponents.hour = self.selectedHour
dateComponents.minute = self.selectedMinute
let userCalendar = Calendar.current // user calendar
let someDateTime = userCalendar.date(from: dateComponents)
This is the code I've used for creating an event for a time interval and it's working fine for me:
func saveEvent(on date: Date, withTitle title: String, forHourse hourse: Int) {
let event = EKEvent(eventStore: eventStore!)
event.title = title
event.startDate = date
event.endDate = date.addingTimeInterval((TimeInterval(hourse * 60 * 60)))
let alarm = EKAlarm(absoluteDate: date)
event.alarms = [alarm]
event.calendar = (eventStore?.defaultCalendarForNewEvents)!
do {
try eventStore?.save(event, span: .thisEvent, commit: true)
} catch {
}
}
I have issue with notification attachment, when I add attachments to Notification it will not working, but when I delete the code for attachments it worked probley with no issue
can anyone try to fix this issue.
here is the function for notification in AppDelegate:
#available(iOS 10.0, *)
func scheduleNotification(currentGame: games) {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let calendar = Calendar(identifier: .gregorian)
let comp = calendar.dateComponents(in:.current, from: dateFormatter.date(from: currentGame.gameDate)!)
let newComponents = DateComponents(calendar: calendar ,year: comp.year ,month: comp.month , day: comp.day, hour: comp.hour, minute: comp.minute ,second: comp.second)
let trigger = UNCalendarNotificationTrigger(dateMatching: newComponents, repeats: false)
let content = UNMutableNotificationContent()
content.title = NSLocalizedString("NOTIFICATION_TITLE", comment: "Game Released")
content.body = "\(currentGame.gameName) Released ✌🏻"
content.sound = UNNotificationSound.default()
content.badge = 1
if let url = NSURL(string: "http://www.ya-techno.com/gamesImage/\(currentGame.gameImage)"){
do {
let attachment = try UNNotificationAttachment(identifier: "image", url: url as URL, options: nil)
content.attachments = [attachment]
} catch {
print("The attachment was not loaded.")
}
}
let request = UNNotificationRequest(identifier:currentGame.gameID, content: content, trigger: trigger)
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().add(request) {(error) in
if let error = error {
print("error: \(error)")
}
}
}
#available(iOS 10.0, *)
func removeAllPendingNotificationRequests(){
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
}
and here is the image from console:
Try the below code
func scheduleNotification(at date: Date) {
let calendar = Calendar(identifier: .gregorian)
let components = calendar.dateComponents(in: .current, from: date)
let newComponents = DateComponents(calendar: calendar, timeZone: .current, month: components.month, day: components.day, hour: components.hour, minute: components.minute)
let trigger = UNCalendarNotificationTrigger(dateMatching: newComponents, repeats: false)
let identifier = ProcessInfo.processInfo.globallyUniqueString
let content = UNMutableNotificationContent()
content.title = "Hello"
content.body = "World"
content.sound = UNNotificationSound.default()
let myImage: UIImage = UIImage(named: "logo.png")!
if let attachment = UNNotificationAttachment.create(identifier: identifier, image: myImage, options: nil) {
// where myImage is any UIImage that follows the
content.attachments = [attachment]
}
let request = UNNotificationRequest.init(identifier: identifier, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { (error) in
// handle error
}
}
Use the below extension to get the image, which you added in your project.
extension UNNotificationAttachment {
/// Save the image to disk
static func create(identifier: String, image: UIImage, options: [NSObject : AnyObject]?) -> UNNotificationAttachment? {
let fileManager = FileManager.default
let tmpSubFolderName = ProcessInfo.processInfo.globallyUniqueString
let tmpSubFolderURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(tmpSubFolderName, isDirectory: true)
do {
try fileManager.createDirectory(at: tmpSubFolderURL, withIntermediateDirectories: true, attributes: nil)
let imageFileIdentifier = identifier+".png"
let fileURL = tmpSubFolderURL.appendingPathComponent(imageFileIdentifier)
guard let imageData = UIImagePNGRepresentation(image) else {
return nil
}
try imageData.write(to: fileURL)
let imageAttachment = try UNNotificationAttachment.init(identifier: imageFileIdentifier, url: fileURL, options: options)
return imageAttachment
} catch {
print("error " + error.localizedDescription)
}
return nil
}
}
I'm trying to schedule a local notification to fire every day (i.e. repeats), at a specific time, but from tomorrow.
i.e "Trigger a notifcation every day at 8pm, from tomorrow"
I've been using this SO question as guidance, and I believe I am doing what it says but I am still getting a notification today when I run the following code (if I schedule the notification before 8pm for instance):
func testDateNotification(){
let content = UNMutableNotificationContent()
content.title = "Test"
content.body = "This is a test"
let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: Date())
let userCalendar = Calendar.current
var components = userCalendar.dateComponents([.hour, .minute], from: tomorrow!)
components.hour = 20
components.minute = 00
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true)
let request = UNNotificationRequest(identifier: "test", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { (error) in
if ((error) != nil){
print("Error \(String(describing: error))")
}
}
}
import UserNotifications
Check for user permission
UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]) {
if $0 { } }
Add notification
let fromDate = Date(timeIntervalSince1970: Double(0.0))
let dateComponent = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute, .second], from: fromDate)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponent, repeats: true)
print(trigger.nextTriggerDate() ?? "nil")
let content = UNMutableNotificationContent()
content.title = "title"
content.body = "body"
let request = UNNotificationRequest(identifier: "identify", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) {
if let error = $0 {
print(error)
return
}else {
print("scheduled")
}
}