【问题标题】:Objective-C monthly notification end of monthObjective-C 月末通知
【发布时间】:2014-04-17 03:53:58
【问题描述】:

我的应用中有一个通知系统,允许用户设置多个通知,它们可以是:

  • 每日
  • 每周
  • 每月

前两个没问题,但第三个我有问题。 假设我们在 3 月,用户将通知设置为在 31 日触发。通知已正确安排,但如果我们在 4 月(30 天),例如,通知安排在 5 月 1 日。

我有两个问题:

  • 如何将通知安排在当月的最后一天?或者让他们在接下来的几个月里优雅地处理这个案子。
  • 如果 3 月 31 日的通知安排正确,下一个通知会安排在 4 月 30 日,然后是 5 月 31 日吗?我的猜测是否定的,将是 3 月 31 日、4 月 1 日和 4 月 31 日。

安排多个通知对我来说不是一个选项,因为苹果有一个限制,如果用户有 6 个每月通知 (6x12) 可以很容易地达到这个限制,而且他们可以有更多。

谢谢,

塞尔吉奥

编辑

抱歉,我没有正确解释自己。 我在正确的日期设置通知没有问题。但是我对重复的工作方式有疑问。如果我将通知设置为从 3 月 31 日开始在每个月的 31 日触发(假设我们在 3 月),第一个通知将在正确的日子出现,但 4 月会发生什么?

再次感谢。

【问题讨论】:

  • 你能发布你用来安排通知的代码吗?

标签: ios objective-c notifications localnotification


【解决方案1】:

您可以使用以下方法获取特定日期当月的最后一天

-(NSDate*)lastDayOfMonthOfDate:(NSDate *)date
{
    NSInteger dayCount = [self numberOfDaysInMonthCountForDate:date];

    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

    [calendar setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];

    NSDateComponents *comp = [calendar components:
                              NSYearCalendarUnit |
                              NSMonthCalendarUnit |
                              NSDayCalendarUnit fromDate:date];

    [comp setDay:dayCount];

    return [calendar dateFromComponents:comp];
}

-(NSInteger)numberOfDaysInMonthCountForDate:(NSDate *)date
{
    NSCalendar *calendar = [[NSCalendar alloc]   initWithCalendarIdentifier:NSGregorianCalendar];

   [calendar setTimeZone:[NSTimeZone timeZoneWithName:TIMEZONE]];

    NSRange dayRange = [calendar rangeOfUnit:NSDayCalendarUnit
                                      inUnit:NSMonthCalendarUnit
                                     forDate:date];

    return dayRange.length;
}

从这些方法中找到最后一天并安排当天的通知

来源:Getting the last day of a month

【讨论】:

  • 谢谢,但这只能解决第一个通知的问题,我已经这样做了。我使用repeatInterval NSMonthCalendarUnit 使用每月通知。问题在于操作系统如何安排以下通知,而不是我设置的第一个通知。谢谢。
  • 谢谢@manujmv。我更新了问题并添加了一些说明。
【解决方案2】:

-[NSCalendar rangeOfUnit:inUnit:forDate:] 将告诉您在特定日期的上下文中,特定日期组件在较大组件中可以采用的最小值和最大值。

如果您使用NSDayCalendarUnitNSMonthCalendarUnit,则结果的length 将是包含过去日期的月份的最后一天。

例如:

NSCalendar * c = [NSCalendar currentCalendar];
NSRange aprilRanger = [c rangeOfUnit:NSDayCalendarUnit 
                              inUnit:NSMonthCalendarUnit 
                             forDate:[NSDate date]];

NSLog(@"%lu", aprilRanger.length);

NSDateComponents * minusTwoMonths = [NSDateComponents new];
[minusTwoMonths setMonth:-2];
NSDate * febDay = [c dateByAddingComponents:minusTwoMonths 
                                  toDate:[NSDate date] 
                                 options:0];
NSRange febRange = [c rangeOfUnit:NSDayCalendarUnit 
                           inUnit:NSMonthCalendarUnit 
                          forDate:febDay];

NSLog(@"%lu", febRange.length);

生产:

30
28

当闰日等奇怪的事情发生时,这也会给你正确的答案。

【讨论】:

  • 感谢您的回答。这允许我将第一个通知设置在当月的有效日期,但问题是下个月将再次是 30 日,或者即使用户选择了 31 日也是 28 日。
  • UILocalNotifications 是严格基于区间的,据我所知。如果您想要“一个月的最后一天”功能,我相信您将不得不每个月重新安排通知。
  • 谢谢乔希。我更新了问题。添加了一些说明。
  • 如果您使用 NSTimer,例如,当计时器触发时,您会使计时器无效并创建一个新计时器。严格来说,您也应该通过每日和每周通知来做到这一点,因为有时它们比预期的时间长或短一个小时。
【解决方案3】:

我必须做的是: 检查当前月份是否有用户请求的日期(最多 31 天)。

  • 如果它没有在最后一天为当月安排正常通知,然后在下个月安排每月通知,则操作系统将处理其余的。

注意:如果当前月份没有请求的日期(2 月 31 日),下个月肯定会有(3 月 31 日)。

  • 如果是,则将每月安排在当前月份。

【讨论】:

    【解决方案4】:

    嘿,这没什么大不了的。

    在您的通知对象中将repeatInterval 设置为NSMonthCalendarUnit

    UILocalNotification *notify = [ [UILocalNotification alloc] init ];
    notify.fireDate = notificationDate;
    notify.repeatInterval = NSMonthCalendarUnit;
    // use NSDayCalendarUnit, NSWeekCalendarUnit for daily or weekly respectively.
    

    谢谢 达米特H

    【讨论】:

    • 谢谢,这不是我的问题。我已将其设置为每月通知。问题是如果我设置一个通知,从 3 月 31 日开始在每个月的 31 日触发(假设我们是在 3 月),第一个通知会在正确的日子出现,但 4 月会发生什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-06
    • 2013-04-28
    • 2011-06-20
    相关资源
    最近更新 更多