Add Reminder List programmatically - swift

I'm building an application that interacts with the macOS Reminder App. I'm trying to create a new Reminder list into which I later can import reminders.
This is what I have so far:
func setCalendar(_ type: EKEntityType) {
let eventStore = EKEventStore()
let newCalendar = EKCalendar(for: type, eventStore: eventStore)
newCalendar.title="newcal"
print("Cal: " + newCalendar.title)
try? eventStore.saveCalendar(newCalendar, commit: true)
}
However, there is no reminder list being created.

The problem is that you have omitted to specify the new calendar's .source. You cannot create a calendar of any kind (event or reminder) without doing that.

Related

Query HealthKit in Widget on Apple Watch

I want to query steps from HealthKit every 15mins to update my Complication via WidgetKit.
In the Timeline Provider getTimeline() I execute the query, create one timeline entry with the steps and set timeline refresh policy to .after(now + 15min).
Currently I am stuck because the refresh is never triggered. The steps are queried and shown after initially setting the complication on the Watchface but never refresh.
`
func getTimeline(in context: Context, completion: #escaping (Timeline<HealthKitWidgetEntry>) -> Void) {
let currentDate = Date()
let refreshMinuteGranuity = 15
let refreshDate = Calendar.current.date(
byAdding: .minute,
value: refreshMinuteGranuity,
to: currentDate
)!
healthData.getTodaysSteps { steps in
let entry = HealthKitWidgetEntry(
date: currentDate, steps: steps
)
let timeline = Timeline(
entries: [entry], policy: .after(refreshDate)
)
print("Next refresh: \(refreshDate)")
completion(timeline)
}
}
`
Any input on how to solve this?
I had the same problem. I was able to work around it by starting an observer like this: enableBackgroundDelivery Health-kit iOS15 not working correctly
In the ChangeHandler you can cause the widget to update itself:
WidgetCenter.shared.reloadAllTimelines()
Be sure you set the Entitlement for "HealthKit Observer Query Background Delivery"

EventKit. How can I get videoconference url from EKEvent

I have an event that has a meet or zoom link. However, I can't find a way to get the link of type https://meet.google.com/.... An example:
let calendars = eventStore.calendars(for: .event)
var events: [EKEvent] = []
for calendar in calendars {
let oneMonthAfter = Date(timeIntervalSinceNow: 30*24*3600)
let predicate = eventStore.predicateForEvents(withStart: Date(), end: oneMonthAfter, calendars: [calendar])
let collection = eventStore.events(matching: predicate)
events.append(contentsOf: collection)
}
let event = events.first! // This event has a meet link associated but I can't get the link
EventKit has a class named EKVirtualConferenceURLDescriptor (more info here). However, the documentation isn't good and only talks about creating a new one, not how we can get it from an existing event.

Empty EKEventStore calendar list after authentication

I would like to grab the names of my calendars on my Mac. I have 1 that's listed as "On My Mac", another (Birthdays) under "Other", and 4 that are pulled in from Google Calendar.
let eventStore = EKEventStore()
eventStore.requestAccess(to: EKEntityType.event) { (accessGranted, error) in
if (accessGranted) {
let calendars = eventStore.calendars(for: .event)
print(calendars)
}
}
The goal is to determine how many days remain until the next event across all selected calendars.
Using the above code, I'm getting back an empty array. How can I access these calendars?

How to delete a donated shortcut in Swift Siri

I have a simple To do style list app, where an added item can have an intent donated so that user can find and mark the item as "completed" without opening the app.
In the Note class I have this function to donate the intent, which works as expected
public func donateMarkNoteAsCompleteIntent() {
let intent = MarkNoteAsCompleteIntent()
intent.content = self.content
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/YYYY"
intent.addedDate = dateFormatter.string(from: self.addedDate)
intent.id = self.id
let interaction = INInteraction(intent: intent, response: nil)
interaction.groupIdentifier = self.id
interaction.donate(completion: nil)
}
My only issue is, when the user uses the shortcut and triggers the app to update the Note item, I want to remove the shortcut so that the user can't trigger it again.
In my intent handle function, I end up calling this function
public func removeMarkNoteAsCompleteIntent() {
INInteraction.deleteAll(completion: nil)
let index = CSSearchableIndex()
index.deleteAllSearchableItems(completionHandler: nil)
}
No matter what combination of things I do here I can't seem to remove the donated shortcut. As soon as a user accepts marking the task as complete, I want the shortcut to no longer be visible in searches from Spotlight, etc. Everything else in the intent handling code is working, its updating the Note item in my database perfectly.
Help would be greatly appreciated.

Notification Center and changing timezones

Swift 4 & >iOS 10.0
I want to schedule a local notification at a certain date and at a given time (let's say 3PM). I want the notifications to always be fired at 3PM, whatever the timezone I am in (automatic rescheduling of notifications according to timezones).
Previously, you could tweak UILocalNotifications' time zone to achieve exactly this, like perfectly explained in this SO post. However, in >iOS 10.0, UILocalNotifications is deprecated.
Here is my code:
func scheduleNotification(title: String, message: String, atDate: Date){
let center = UNUserNotificationCenter.current()
// Create content
let content = UNMutableNotificationContent()
content.title = title
content.body = message
content.sound = UNNotificationSound.default()
// Create trigger
let calendar = Calendar(identifier: .gregorian)
let triggerDate = calendar.dateComponents([.year,.month,.day,.hour,.minute,.second,], from: atDate)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate, repeats: false)
// Create identifier
let identifier = "\(UUID())"
// Create request & add to center
let request = UNNotificationRequest(identifier: identifier,
content: content,
trigger: trigger)
center.add(request, withCompletionHandler: { (error) in
})
}
Question:
How do you make the notification triggers properly with changing timezones ?
So, I managed to make it work. The triggerDate has a timeZone variable which is automatically nil, exactly like UILocalNotification.
triggerDate.timeZone behaves exactly like UILocalNotification.timeZone (behaviour described in this post, the same as mentioned in the question).
One of the reason it did not seem to work on the simulator was because I was not restarting the simulator when changing the timezone. Restarting will make everything work as expected.
Nota bene: Maybe a restart is not mandatory but since it's not obvious how much time a running simulator will take to detect the new timezone, I think restarting it is the most efficient solution.