Create weekly swift ios local notifications - ios

I can create daily notifications but not weekly ones using swift 3 ios 10 User Notifications framework. Daily works fine but when I add in the .weekday parameter it doesn't send me a notification.
The code is:
for i in 1 ... 7
{
let center = UNUserNotificationCenter.current();
let content = UNMutableNotificationContent();
content.title = "Title";
content.body = "content";
content.sound = UNNotificationSound.default();
var dateComponents = DateComponents();
dateComponents.weekday = i;
// hours is 00 to 11 in string format
if (daynight == "am")
{
dateComponents.hour = Int(hours);
}
else
{
dateComponents.hour = Int(hours)! + 12;
}
// mins is 00 to 59 in string format
dateComponents.minute = Int(mins);
dateComponents.second = 0;
let date = Calendar.current.date(from: dateComponents);
// tiriggerDaily works without weekday for daily but adding weekday doesn't make it weekly
let triggerDaily = Calendar.current.dateComponents([.weekday, .hour, .minute, .second], from: date!);
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: true);
let identifier = // a uuid;
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger);
center.add(request, withCompletionHandler:
{
(error) in
if let error = error
{
// Error happened
print("Error: ");
print(error);
}
});
Need to get code to figure out weekly. Used this as guidance: https://useyourloaf.com/blog/local-notifications-with-ios-10/
An example of what I want is this:
A user selects Monday, 11:25pm and it is a Monday at 11:23pm.
Then the user should get a notification in two minutes plus one the following week and so on.
Some other notes/questions:
1. Do you have to wait a week for weekly notifications to start? Like in the example above will it start the following week?
Just a thought since I can't get this working right yet.

Related

Daily LocalNotification with Start & End Time

I want a notification to repeat daily, but with the start time, end time & frequency(fixed) given.
Say, start time is 10am, endTime 6pm & frequency is every 3hrs, then it should trigger notification at 10am, 1pm, 4pm respectively.
Note:- the application has 3 other local notification (with different title & body), so need to differentiate the notifications as user can stop any of these notifications anytime.
Tried with DLLocalNotification but it didn't solve my problem.
DLNotificationScheduler().repeatsFromToDate (identifier: String, alertTitle: String, alertBody: String, fromDate: Date, toDate: Date, interval: Double, repeats: RepeatingInterval, category: String = " ", sound: String = " ")
Any help would be highly appreciated
For posting the local notification with repeat, you can use below code :
let content = UNMutableNotificationContent()
content.title = "Pizza Time!!"
content.body = "Monday is Pizza Day"
content.categoryIdentifier = "pizza.reminder.category"
//Date component trigger
var dateComponents = DateComponents()
//example for Gregorian calendar. Every Monday at 11:30AM
dateComponents.hour = 11
dateComponents.minute = 30
dateComponents.weekday = 2
// for testing, notification at the top of the minute.
dateComponents.second = 0
let trigger = UNCalendarNotificationTrigger(
dateMatching: dateComponents,
repeats: true)
let request = UNNotificationRequest(identifier: "pizza.reminder", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { (error) in
if let error = error {
print("error in pizza reminder: \(error.localizedDescription)")
}
}
You can add multiple types of notification by defining the different identifiers for each.
To Stop the local notification,
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: ["pizza.reminder"])
To get the notification of the local notifications which are still remaining to be posted, you can use below code
UNUserNotificationCenter.current().getPendingNotificationRequests {
(requests) in
displayString += "count:\(requests.count)\t"
for request in requests{
displayString += request.identifier + "\t"
}
print(displayString)
}
This things are sufficient enough to add some logic and meet your requirements.
For more information you can follow :
https://makeapppie.com/2017/01/31/how-to-repeat-local-notifications/

How to create dateComponents from Date stored in CoreData

I am trying to create dateComponents from Date stored in CoreData from UIDatePicker. However, I am not able to make it. I am first converting Date which is stored in editnotes?.sSelectedDate into dateComponents and then using the dateComponents for triggering my notifications.
Here is what I am doing:
var date = Date()
if let editnote = editnotes
{
date = editnote.sSelectedDate
}
else
{
print("nil")
}
let calendar = NSCalendar.current
let unitFlags = Set<Calendar.Component>([.day, .month, .year, .hour, .minute])
let anchorComponents = calendar.dateComponents(unitFlags, from: date)
var dateInfo1 = DateComponents()
dateInfo1.day = anchorComponents.day
dateInfo1.month = anchorComponents.month
dateInfo1.hour = anchorComponents.hour
dateInfo1.minute = anchorComponents.minute
dateInfo1.year = anchorComponents.year
let trigger = UNCalendarNotificationTrigger(dateMatching:dateInfo1, repeats: false)
I am doing this:
if let editnote = editnotes
{
date = editnote.sSelectedDate
}
else
{
print("nil")
}
to unwrap the optional but it's not working still. Continue reading!
I know I can use anchorComponents but that wasn't working so I copied those into a new DataComponents instance.
I am trying to print the what is stored indateInfo1.hour and I get
Optional(2)
I reckon this is the reason why dateComponents is not working for triggering notifications at scheduled time.
Help will be appreciated?
Explicit cast it like this
let anchorComponents = calendar.dateComponents(unitFlags, from: date) as! DateComponents
You'r using anchorComponents.days / .hours / .days / .minutes it's all optional. Instead, I'd used initialiser for DateComponents where you explicitly set your properties you needed. But I think you'r just doing something wrong and that's why notification not working and the reason is not date. You can simply check it by setting from date to current date plus few seconds to see whether you'll get notification or not

Multi-Day All Day Events with Event Kit not at top of calendar

All-day events that span multiple days in Event Kit are appearing at the bottom of the list of events for that day.
For example if I have a multi-day all day event from 1 January to 3 January and then look at the calendar for 2 January.
2 January
8-10am Meeting
12pm - 1pm Lunch
All-Day Event*
Code
let startDate = NSCalendar.currentCalendar().startOfDayForDate(Dates.dateObject)
let endDate = startDate.dateByAddingTimeInterval(Double((60 * 60 * 24))
let calendars = eventStore.calendarsForEntityType(.Event)
var selectedCalendars = [EKCalendar]()
for cal in calendars {
if (NSUserDefaults.standardUserDefaults().boolForKey(cal.calendarIdentifier) != false) {
selectedCalendars.append(cal)
}
}
let eventsPredicate = eventStore.predicateForEventsWithStartDate(startDate, endDate: endDate, calendars: selectedCalendars)
events = eventStore.eventsMatchingPredicate(eventsPredicate)
To solve this, the start date and end date for the predicate has to be 00:00:00 to 23:59:59 (rather than 00:00:00 to 00:00:00).
The code was modified as below.
let startDate = NSCalendar.currentCalendar().startOfDayForDate(Dates.dateObject)
let endDate = startDate.dateByAddingTimeInterval(Double(((60 * 60 * 24) - 1))
let calendars = eventStore.calendarsForEntityType(.Event)
var selectedCalendars = [EKCalendar]()
for cal in calendars {
if (NSUserDefaults.standardUserDefaults().boolForKey(cal.calendarIdentifier) != false) {
selectedCalendars.append(cal)
}
}
let eventsPredicate = eventStore.predicateForEventsWithStartDate(startDate, endDate: endDate, calendars: selectedCalendars)
events = eventStore.eventsMatchingPredicate(eventsPredicate)

How do I set an NSCalendarUnitMinute repeatInterval on iOS 10 UserNotifications?

In UILocalNotification we use NSCalendarUnitMinute like repetition ..... but I can't find in iOS 10 UserNotification doc ... How can I use NSCalendarUnitMinute like repetition in iOS 10 UserNotification?
here is the code which will schedule local notification at 8:30 pm and will repeat after every one minute.
UILocalNotification* localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = pickerDate;
localNotification.alertBody = self.textField.text;
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.repeatInterval = NSCalendarUnitMinute;
localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
Although it appears that the old notifications framework had better support regarding this, it's only until, we realise that the new one is better!!
I had similar problems, and below is a sample of how the old notifications can go hand in hand with the new ones.
To be on a safer side, this is Swift2.3.
// Retrieve interval to be used for repeating the notification
private func retrieveRepeatInterval(repeatTemp: RepeatInterval) {
switch repeatTemp {
case .Never:
if #available(iOS 10.0, *) {
toDateComponents = NSCalendar.currentCalendar().components([.Hour, .Minute, .Day, .Month, .Year], fromDate: timeTemp!)
toDateComponents.second = 0
repeatNotification = false
} else {
repeatIntervalTemp = nil
}
case .EveryMinute:
if #available(iOS 10.0, *) {
toDateComponents.second = 0
repeatNotification = true
} else {
repeatIntervalTemp = .Minute
}
case .EveryHour:
if #available(iOS 10.0, *) {
toDateComponents = NSCalendar.currentCalendar().components([.Minute], fromDate: timeTemp!)
toDateComponents.second = 0
repeatNotification = true
} else {
repeatIntervalTemp = .Hour
}
case .EveryDay:
if #available(iOS 10.0, *) {
toDateComponents = NSCalendar.currentCalendar().components([.Hour, .Minute], fromDate: timeTemp!)
toDateComponents.second = 0
repeatNotification = true
} else {
repeatIntervalTemp = .Day
}
case .EveryWeek:
if #available(iOS 10.0, *) {
toDateComponents = NSCalendar.currentCalendar().components([.Hour, .Minute, .Weekday], fromDate: timeTemp!)
toDateComponents.second = 0
repeatNotification = true
} else {
repeatIntervalTemp = .WeekOfYear
}
case .EveryMonth:
if #available(iOS 10.0, *) {
toDateComponents = NSCalendar.currentCalendar().components([.Hour, .Minute, .Day], fromDate: timeTemp!)
toDateComponents.second = 0
repeatNotification = true
} else {
repeatIntervalTemp = .Month
}
case .EveryYear:
if #available(iOS 10.0, *) {
toDateComponents = NSCalendar.currentCalendar().components([.Hour, .Minute, .Day, .Month], fromDate: timeTemp!)
toDateComponents.second = 0
repeatNotification = true
} else {
repeatIntervalTemp = .Year
}
}
}
Although this isn't exhaustive, I've pretty much covered everything from a minute to a year.
And to be more detailed,
// RepeatInterval
enum RepeatInterval : String, CustomStringConvertible {
case Never = "Never"
case EveryMinute = "Every Minute"
case EveryHour = "Every Hour"
case EveryDay = "Every Day"
case EveryWeek = "Every Week"
case EveryMonth = "Every Month"
case EveryYear = "Every Year"
var description : String { return rawValue }
static let allValues = [Never, EveryMinute, EveryHour, EveryDay, EveryWeek, EveryMonth, EveryYear]
}
var repeatTemp: RepeatInterval?
var repeatIntervalTemp: NSCalendarUnit?
var timeTemp: NSDate?
var toDateComponents = NSDateComponents()
As this works for me, it should probably for the rest of you. Please try and let me know if there is an issue.
And, for the exact solution to this question, I'd advise the below.
(Probably, Apple didn't think about such a scenario, but it can be handled)
Schedule a notification for 8:30 PM
When the notification is triggered, remove it and schedule another notification with a different identifier, for the NSCalendarUnitMinute equivalent shown above.
Voila, it works!! (Or did it not?)
Use a UNCalendarNotificationTrigger with DateComponents instead of NSCalendar:
var date = DateComponents()
date.hour = 8
date.minute = 30
let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: true)
let content = UNNotificationContent()
// edit your content
let notification = UNNotificationRequest(identifier: "myNotification", content: content, trigger: trigger)
You set up the date with a DateComponents instance and specify if the notification should repeat with the repeats parameter of the UNCalendarNotificationTrigger initializer.
UNCalendarNotificationTrigger Documentation
Just a heads up that there is a typo in the Apple Docs (as of 6/13). If you use NSDateComponents instead of DateComponents, you will need to explicitly cast your date as DateComponents in the dateMatching parameter.
In response to your comment, I don't believe the behavior you want (changing the frequency of your repeated notification) is supported by UNCalendarNotificationTrigger.
Bear with me this is my first post.
We needed the 1 minute repeat interval for our app in ios 10, and used as a workaround a combination the old and new framework.
scheduling the repeating local notifications with the old:
UILocalNotification *ln = [[UILocalNotification alloc] init];
...
ln.repeatInterval = kCFCalendarUnitMinute;
ln.userInfo = #{#"alarmID": ...}
...
[[UIApplication sharedApplication] scheduleLocalNotification:ln];
This will create and schedule the usual repeating LNs that will show up as UNNotification with a UNLegacyNotificationTrigger
I used a alarmID to connect old and new framework.
Try:
UNUserNotificationCenter* center = [UNUserNotificationCenter
currentNotificationCenter];
[center getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> * _Nonnull requests) {
NSLog(#"----------------- PendingNotificationRequests %i -------------- ", (int)requests.count);
for (UNNotificationRequest *req in requests) {
UNNotificationTrigger *trigger = req.trigger;
NSLog(#"trigger %#", trigger);
}
}];
responding to actions and fire-ing notifications, manipulating the notification centre:
With the new framework UNUserNotificationCenter methods:
willPresentNotification:
didReceiveNotificationResponse:
Request authorization and category registration I did for both frameworks in the usual way.
Hope this helps

Having trouble scheduling local notification to fire at specific time and date in swift

I am trying to schedule a notification at a certain time in swift. My TimeString is a string that looks like 08:32 or 12:23. When I try to fire on this specific date and time, the notification only fires on the specific date however not the specific time. For instance if I change the year to 2016 it won't fire. If I change the month it won't fire. Yet regardless of what time I put in, if the date matches the current date, I am writing this on 1/28/2015, the notification fires regardless of time, In fact it fires as soon as I close the application as my code is in
func applicationDidEnterBackground(application: UIApplication) {
}
My code does compile so I don't think there is an error in my code.
Is there any way to fire a notification at a specific time and not just a date in swift, and if so how do I implement this.
var timeString : String = "2015-01-28 " + TimeString;
println(timeString);
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm"
formatter.timeZone = NSTimeZone(abbreviation: "GMT");
var date = formatter.dateFromString(timeString)
var localNotification:UILocalNotification = UILocalNotification()
localNotification.alertAction = "Block"
localNotification.alertBody = block.description() + " Started";
localNotification.fireDate = date
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
Try using this approach to set your date:
let calendar = NSCalendar.currentCalendar()
let calendarComponents = NSDateComponents()
calendarComponents.hour = 8 //you can get you time components
calendarComponents.second = 0 //from your string rather than
calendarComponents.minute = 0 //using fixed values
calendarComponents.day = 28
calendarComponents.year = 2015
calendarComponents.month = 1
let dateToFire = calendar.dateFromComponents(calendarComponents)
It worked for me. Hope this helps. :)

Resources