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
}
}
Related
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)
I've set the user notification. They got deliver well but the badge on the app icon is always one.
Here's my code:
let center = UNUserNotificationCenter.current()
let options: UNAuthorizationOptions = [.alert, .badge, .sound];
center.requestAuthorization(options: options) {
(granted, error) in
if !granted {
// ask for permission
}
}
When the use click the button i schedule the notif:
#IBAction func saveBtnPressed(sender: UIButton) {
scheduleNotif()
}
Here's the scheduleNotif function
func scheduleNotif() {
let dateformatter = DateFormatter()
dateformatter.dateStyle = DateFormatter.Style.medium
dateformatter.timeStyle = DateFormatter.Style.short
let dateFromString = dateformatter.date(from: selectDateTextField.text!)
let fireDateOfNotification: Date = dateFromString!
//Notif are enabled
let content = UNMutableNotificationContent()
content.title = notifTitleTextField.text!
content.body = notifNoteTextView.text
content.sound = UNNotificationSound.default()
content.badge = UIApplication.shared.applicationIconBadgeNumber + 1 as NSNumber
var trigger: UNCalendarNotificationTrigger
var triggerDate = DateComponents()
trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate, repeats: false)
let titleNospace = notifTitleTextField.text?.replacingOccurrences(of: " ", with: "")
var identifier = titleNospace
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
self.center.add(request, withCompletionHandler: { (error) in
if let error = error {
print(error.localizedDescription)
}
})
}
Any idea why the badge will always display one and never increment as the notifications are delivered?
Thank you
I think you need to increment applicationIconBadgeNumber. So replace
content.badge = UIApplication.shared.applicationIconBadgeNumber + 1 as NSNumber
By:
UIApplication.shared.applicationIconBadgeNumber += 1
content.badge = UIApplication.shared.applicationIconBadgeNumber as NSNumber
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.
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")
}
}
I have a local notification and I added an action to it. How should I do so that when the action is tapped, the local notification is fired again after 15 minutes?
Here is the code and the extension so that the notification can be showed using an UIImage:
extension UNNotificationAttachment {
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
}
}
func scheduleNotification() {
removeNotification()
if shouldRemind && dueDate > Date() {
let content = UNMutableNotificationContent()
content.title = "Reminder:"
content.body = text
content.sound = UNNotificationSound.default()
let calendar = Calendar(identifier: .gregorian)
let components = calendar.dateComponents([.month, .day, .hour, .minute], from: dueDate)
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: false)
let identifier = ProcessInfo.processInfo.globallyUniqueString
if let attachment = UNNotificationAttachment.create(identifier: identifier, image: notificationImage, options: nil) {
content.attachments = [attachment]
}
let action = UNNotificationAction(identifier: "remindLater", title: "Remind me later", options: [])
let category = UNNotificationCategory(identifier: "category", actions: [action], intentIdentifiers: [], options: [])
UNUserNotificationCenter.current().setNotificationCategories([category])
content.categoryIdentifier = "category"
let request = UNNotificationRequest(identifier: "\(itemID)", content: content, trigger: trigger)
let center = UNUserNotificationCenter.current()
center.add(request)
}
}
Just call a modified version scheduleNotification again in the action handler when the user activates the action. I would definitely create a function variable as a TimeInterval or a boolean which determines the trigger time of the notification.