I tried to add an alarm (EKAlarm) to a reminder (EKReminder). Almost everything works fine: The reminder is added in the "Reminders.app" and gets fired at the right time.
But somehow (in contrast to a manually created reminder) the firing date/time is not showing in the detail label of the reminder in the "Reminders.app" and it's not appearing in the NotificationCenter as upcoming reminder either.
This is my (slightly abbreviated) code:
// EventStore
var store = EKEventStore()
// Reminder
var reminder = EKReminder(eventStore: store)
reminder.title = "Test"
reminder.calendar = store.defaultCalendarForNewReminders()
// Add alarm to reminder
reminder.addAlarm(EKAlarm(absoluteDate: datePicker.date))
// Add it to Reminders.app
store.saveReminder(reminder, commit: true, error: &error)
Am I missing anything? Thx for your help in advance.
Related
I am adding a local notification feature to my iOS app which will fire up a notification / alert on a specified time e.g. 7am daily. So I setup the alert using the code below:
let content = UNMutableNotificationContent()
content.title = "Planned transactions due today"
content.body = "You have [NUMBER] scheduled income and [NUMBER] planned expenses due for today."
content.categoryIdentifier = "alarm"
content.userInfo = ["customData": "fizzbuzz"]
content.sound = UNNotificationSound.default
let date = Date(hour: 7, minute: 0, second: 0) //custom initializer from Date extension
let dateComponents = Calendar.current.dateComponents([.hour, .minute], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
let request = UNNotificationRequest(identifier: "Reminder", content: content, trigger: trigger)
center.add(request) { (error) in
if let error = error {
print("Error scheduling notification: \(error.localizedDescription)")
}
}
It works perfectly. But what I want to achieve is to add more useful information within the local notification's body, like replacing the [NUMBER] to an actual number which is derrived from a query from core data.
I need help on how to pull this off. I've looked at implementations using UNNotificationServiceExtension and UNNotificationContentExtension. But I can't seem to make it work. I was unable to find any implementations of UNNotificationServiceExtension that applies to local notification – I could be wrong but I think it's only for push notifications.
I've also tried implementing UNUserNotificationCenterDelegate on the AppDelegate to intercept the notification as it is being triggered. func userNotificationCenter(willPresent:) method allows me to get the notification but there seems to be no way for me to change the .content property as it is get-only.
So basically, I just want to be able to change the body content of the notification before it is being displayed.
My solution isn't the best, but to achive this, i do the following at each app launch:
first cancel the next notifications,
then update it with a new content.
It works fine if the app is used at a regular basis.
there is some something called BGTaskScheduler. Apple said that it is a
A class for scheduling task requests that launch your app in the
background.
https://developer.apple.com/documentation/backgroundtasks/bgtaskscheduler
Maybe you should check for it
So I have an app where a reminder is created and added to the Reminder App on your iPhone. But in the Reminders App they have different List or categories. I want to create my own category for my app. And then I want to add reminders to that category.
So a snippet of my code is basically a button which then adds a reminder to a Random List(I think). But I want the reminder to be sent to a specific list(In the reminders app) that the app(my app) needs to create. And if the list is already created I need to use that list.
var eventStore = EKEventStore()
#IBAction func ActSetReminder(_ sender: Any) {
let reminder = EKReminder(eventStore: self.eventStore)
reminder.calendar = eventStore.defaultCalendarForNewReminders()
reminder.title = "the title doesn't matter to you"
reminder.isCompleted = false
}
This is a super basic version of that method it does other stuff that aren't important for this problem. there are other tuff in the class like the viewedload and that stuff.
If you need more code or have any questions ask me!
In terms of the Calendar framework a Reminder Category is just a calendar.
You can use this method, it checks if a (reminder) calendar for the bundle name exists. If it does return it, if not create one.
The method assumes that there is a property eventStore holding the EKEventStore instance.
func reminderCategory() throws -> EKCalendar {
let calendars = eventStore.calendars(for: .reminder)
let bundleName = Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as! String
if let bundleCalendar = calendars.first(where: {$0.title == bundleName}) { return bundleCalendar }
let calendar = EKCalendar(for: .reminder, eventStore: eventStore)
calendar.title = bundleName
calendar.source = eventStore.defaultCalendarForNewReminders()?.source
try eventStore.saveCalendar(calendar, commit: true)
return calendar
}
I want to make an app just like iOS Reminders app. My problem is the custom repeat part. We can set custom repeats like "Every 2 Months on the third Monday"(the screenshot below) but I don't know how to implement this sort of repeats with User Notification.
What should I have do?
Although the question might be abroad to be fully answered, I would post an answer that should scratch the surface of how you could achieve it by using user notifications.
If you are aiming to let the displaying of the notification is based on a specific date/interval -as you mentioned "Every 2 Months on the third Monday"-, then you should work with UNCalendarNotificationTrigger:
The date and time at which to deliver a local notification.
Example:
import UserNotifications
// first, you declare the content of the notification:
let content = UNMutableNotificationContent()
content.title = "Notification Title"
content.subtitle = "Notification Subtitle"
content.body = "Notification Body"
// now, you should declare the UNCalendarNotificationTrigger instance,
// but before that, you'd need to describe what's the date matching for firing it:
// for instance, this means it should get fired every Monday, at 10:30:
var date = DateComponents()
date.weekday = 2
date.hour = 10
date.minute = 30
// declaring the trigger
let calendarTrigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: true)
// creating a request and add it to the notification center
let request = UNNotificationRequest(identifier: "notification-identifier", content: content, trigger: calendarTrigger)
UNUserNotificationCenter.current().add(request)
I'm trying to send a local notification at scheduled time. But the notifications does not appear on the screen, but it is showing in the notification center when I swipe down.
This is what I'm trying to achieve This is what I getting.
This code is from my AppDelegate's didFinishLaunchingWithOptions().
// Setup local push notifications
application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: [UIUserNotificationType.Alert, UIUserNotificationType.Badge, UIUserNotificationType.Sound], categories: nil))
scheduleNotifications()
And this is the code for scheduleNotifications()
func scheduleNotifications() {
// create a corresponding local notification
let notification = UILocalNotification()
// Get today's date, time and year
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([NSCalendarUnit.Day, NSCalendarUnit.Month, NSCalendarUnit.Year], fromDate: NSDate())
// Sets the fire time to 2pm/1400 hours to anticipate user for lunch time
components.hour = 19
components.minute = 13
components.second = 00
notification.fireDate = components.date // Sets the fire date
notification.alertBody = "Enjoyed your lunch? Don't forget to track your expenses!"
notification.alertAction = "Add expense"
notification.repeatInterval = NSCalendarUnit.Day // Repeats the notifications daily
UIApplication.sharedApplication().scheduleLocalNotification(notification)
}
Any help would be appreciated. Thanks!
Your issue is the way you are converting the NSDateComponents object to an NSDate.
Simply calling components.date without setting a calendar for the NSDateComponents object will return nil.
Try using this instead:
notification.fireDate = calendar.dateFromComponents(components)
Alternatively, you can set the calendar property on the components object:
components.calendar = calendar
Because you are setting the fireDate property on the notification object to nil, it will fire immediately, i.e. before you have a chance to close the app and lock the screen. This behavour is documented in the UILocalNotification class reference
To me, when phone is connected with a cable, then notification shows up only in notification center - banner is not displayed when app is in foreground.
When cable is disconnected, then the banner is presented over the app.
I get the same odd behavior. Just created a new project to test your code.
What i noticed when you change your fireDate to:
notification.fireDate = NSDate(timeIntervalSinceNow: 10)
You will get your wanted behavior.
Hope that helps a little!
Check Settings > YourApp > Notifications.
Verify the permissions there. "Do Not Disturb" should also not be active.
I am trying to run a particular function with background execution at a certain time each morning. Here's what I have figured out...
func getCurrentTime() { //Is called every minuite by a timer
let date = NSDate()
let formatter = NSDateFormatter()
formatter.timeStyle = .ShortStyle
var stringValue = formatter.stringFromDate(date)
if stringValue == "7:00 AM" {
sendPushAlert()//Defined elsewhere in code, executes desired code
}
}
However, that does not run in the background (e.g. when app not open), and seems like a clunky way to do things.
So, How do I run background execution at a certain time each morning?
Or, is there a better way to fetch data to show in a push notification?
Thanks!!!!!!
You can't force iOS to launch your app at a specific time.
If all you want to do is send a notification at a specific time, schedule a local notification. If the user opens your notification then your app will launch.