Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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];
like image 715
S.J Avatar asked Jun 14 '16 06:06

S.J


3 Answers

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)

  1. Schedule a notification for 8:30 PM
  2. When the notification is triggered, remove it and schedule another notification with a different identifier, for the NSCalendarUnitMinute equivalent shown above.
  3. Voila, it works!! (Or did it not?)
like image 131
Shyam Avatar answered Oct 13 '22 18:10

Shyam


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.

like image 39
JAL Avatar answered Oct 13 '22 20:10

JAL


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.

  1. 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);
    }
}];
  1. responding to actions and fire-ing notifications, manipulating the notification centre:

With the new framework UNUserNotificationCenter methods: willPresentNotification: didReceiveNotificationResponse:

  1. Request authorization and category registration I did for both frameworks in the usual way.

Hope this helps

like image 36
MauritsK Avatar answered Oct 13 '22 18:10

MauritsK