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

3

9

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];
Longtin answered 14/6, 2016 at 6:18 Comment(1)
Check out this answerTreenware
U
3

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?)
Unaffected answered 30/9, 2016 at 6:0 Comment(2)
How do you know the notification has been triggered, so to schedule the next? I've seen suggestions of using a notification service extension but they only work for remote notifications :(Bluebell
@CMash. You are right.. Sorry for the wrong info, provided. I was playing around with this, and seem to have it figured out. But, looks like I wasn't able to. :( Still, I'd say the NSDateComponents, is pretty clear? If anyone needs to use it.Unaffected
A
1

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.

Attired answered 14/6, 2016 at 6:21 Comment(12)
I want to post UserNotification tomorrow at 8:30 pm that will repeat every minute, How to do that in UserNotification.Longtin
@Longtin I don't see any methods in the API to change the frequency of a notification like you are asking. I only see repeat options once per day. Was that possible with UILocalNotification? What you could do is in the handler for the first notification set up a new notification for one minute after the current one fired. I'll keep looking for a way to accomplish the behavior you want.Attired
Have you read through the UserNotifications docs?Attired
@Longtin Yeah, I don't think that is supported. Maybe someone else has a better answer...Attired
Is there any way to ask directly to Apple engineer who deliver this presentation. developer.apple.com/videos/play/wwdc2016/707 OR we can also post questions in wwdc.Longtin
isn't UILocalNotification is better that is capable of doing that and UserNotification is not .........Longtin
@Longtin I can try to ask at one of the dev labs at WWDC tomorrow. Can you add the UILocalNotification code that accomplishes this to your question and I will see if I can port it over?Attired
hi, any updates regarding the repeat frequency in User Notification.Longtin
@Longtin this behavior is not supported in iOS 10. please consider duping a bug report: openradar.me/26855019Sideways
Any updates on this? I can't see any obvious reasons why minute interval wouldn't be allowed?Kerk
@Kerk I think this is unsupported by the API. See UserNotification in 3 days then repeat every day/hour - iOS 10Attired
I'm trying to answer this question but whatever I do the notification doesn't come through. I wrote let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents as DateComponents, repeats: false) I tried with repeating: true, I also tried without the as DateComponents but none worked. I'm not sure if this is a timezone thing. As a tangent question, if you want to set 10:30pm Mon for US, would you just do: dateComponents.minute = 30; dateComponents.hour = 22 ; dateComponents.day = 2Ecosystem
J
1

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

Jennie answered 27/9, 2016 at 13:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.