根据后台时间激活本地通知 [英] Activate local notification based on time in the background

查看:41
本文介绍了根据后台时间激活本地通知的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我有一个包含重复间隔本地通知的应用程序,我想添加一个功能,该功能将在睡眠时间暂停通知.

So I have an app that includes repeat intervals local notification and I would like to add a feature that will pause the notifications during sleep time.

到目前为止,我已经为用户创建了两个日期选择器,以明确他们希望什么时间停止重复间隔以及什么时间自动重新开始.并且我为他们添加了一个uiswitch来激活睡眠模式或忽略该功能.

So far, I have created two datepickers for the user to spicify what time they would like to stop the repeat interval and what time to restart again automatically. And I have added a uiswitch for them to activate the sleep mode or ignore the feature.

现在,我将如何使我的主要uipickerview-(他们从此处从那里选择通知)-听uiswitch(如果已打开),然后在我的第一个datepicker到来时暂停通知并重新初始化第二个日期选择器发出通知的时间?

Now, how would I make my main uipickerview -( which they choose there notification from here) - to listen to the uiswitch if it is on, then it pause the notifications at the time that comes from my first datepicker and reintitiate the notifications at the time that comes from the second datepicker?

我已经设置了datepickers和uiswitch,但不知道如何使用uipickerview来实现它.是否应在DidSelectRow方法下进行?还是appdelegate中的方法(如DidEnterBackground)?

I have already setup my datepickers and my uiswitch but have no idea how to implement it with my uipickerview.. Should it be under the method of DidSelectRow? Or a method in appdelegate ( like DidEnterBackground)?

请询问您是否需要更多信息或代码来理解这个想法并为我提供帮助.谢谢.

Please ask if you need more info or codes to understand the idea and help me. Thanks.

添加:

这是我为日期选择器准备的代码,但是,我只是缺少将其正确添加到选择器视图的连接.

Here is my code that I have prepared for the datepicker, however, I'm just missing the connection to add it to my picker view properly.

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
dateFormatter.timeZone=[NSTimeZone defaultTimeZone];
dateFormatter.timeStyle=NSDateFormatterShortStyle;
dateFormatter.dateStyle=NSDateFormatterShortStyle;
NSString *dateTimeString=[dateFormatter stringFromDate:startTime.date];
NSLog(@"Start time is %@",dateTimeString);


NSDateFormatter *dateFormatter2 = [[NSDateFormatter alloc]init];
dateFormatter2.timeZone=[NSTimeZone defaultTimeZone];
dateFormatter2.timeStyle=NSDateFormatterShortStyle;
dateFormatter2.dateStyle=NSDateFormatterShortStyle;
NSString *dateTimeString2=[dateFormatter2 stringFromDate:endTime.date];
NSLog(@"End time is %@",dateTimeString2);

我也有这段代码可以在时间之间进行比较:

I also have this code to compare between the times:

if ([[NSDate date] isEqualToDate:startTime.date]) {
NSLog(@"currentDate is equal to startTime"); 
}

if ([[NSDate date] isEqualToDate:endTime.date]) {
NSLog(@"currentDate is equal to endTime"); 
}

推荐答案

iOS不支持在两个特定日期/时间之间发布本地重复通知.此外,与基于地理位置的通知不同,当不在前台时,不会向应用程序发出已触发通知的警报.因此,我们需要通过在用户未入睡时创建许多单独的通知来解决此问题.

Posting a local repeating notification between two specific dates/times is not supported by iOS. Additionally, unlike geo-based notifications, the app is not alerted of fired notifications when not in the foreground. So we need to work around this by creating many separate notifications for the time the user isn't asleep.

请按照以下步骤创建基本解决方案:

Follow these steps to create a basic solution:

  1. 将控件连接到视图控制器标题中的IBOutlets:

  1. Connect your controls to IBOutlets in your view controller's header:

SomeViewController.h:

@interface SomeViewController : UIViewController

@property (weak, nonatomic) IBOutlet UISwitch *sleepToggleSwitch;
@property (weak, nonatomic) IBOutlet UIDatePicker *notificationIgnoreStartTime;
@property (weak, nonatomic) IBOutlet UIDatePicker *notificationIgnoreEndTime;
@property (weak, nonatomic) IBOutlet UIPickerView *notificationTypePickerView;

@end

  • 创建IBAction方法,并在视图控制器的实现文件中为每个控件(两个UIDatePickers,一个UISwitch和一个UIPickerView)连接.每个方法都应调用私有方法 startUserOptionInteractionTimer .

    SomeViewController.m:

    - (IBAction)noNotificationPeriodStartDateChanged:(id)sender
    {
        [self startUserOptionInteractionTimer];
    }
    
    - (IBAction)noNotificationPeriodEndDateChanged:(id)sender
    {
        [self startUserOptionInteractionTimer];
    }
    
    - (IBAction)sleepToggleSwitchToggled:(id)sender
    {
        [self startUserOptionInteractionTimer];
    }
    
    - (IBAction)notificationTypeChanged:(id)sender
    {
        [self startUserOptionInteractionTimer];
    }
    

  • startUserOptionInteractionTimer 私有方法中,我们(重新)启动NSTimer.我们在此处使用计时器,这样,如果用户更改日期或快速切换开关(他们很可能会这样做),您就不会拆解并迅速设置通知.(应在实现文件的接口延续中声明NSTimer属性 userOptionInteractionTimer .)

  • In the startUserOptionInteractionTimer private method, we (re)start an NSTimer. We use a timer here so that if the user changes the dates or toggles the switch quickly - which they are likely to do - you don't tear down and set up the notifications quickly in succession. (The NSTimer property userOptionInteractionTimer should be declared in the interface continuation of the implementation file).

    SomeViewController.m:

    - (void)startUserOptionInteractionTimer
    {
        // Remove any existing timer
        [self.userOptionInteractionTimer invalidate];
        self.userOptionInteractionTimer = [NSTimer scheduledTimerWithTimeInterval:4.f
                                                                           target:self
                                                                         selector:@selector(setupNotifications)
                                                                         userInfo:nil
                                                                          repeats:NO];
    }
    

  • 创建另一个私有方法来拆除先前存在的通知并设置新通知.

  • Create another private method to tear down pre-existing notifications and setup the new ones.

    在此处设置通知取决于您要通知用户的时间和间隔.假设您要每小时通知一次用户,并且该用户启用了睡眠功能,那么您需要为每天设置的每小时设置14-18条通知(取决于用户的睡眠时间).

    Setting up the notifications here depends on how long and how often you want to notify your user. Let's say that you want to notify your user every hour and the user has the sleep feature enabled, then you would setup 14-18 notifications (depending on how long the user sleeps) for each hour that repeat daily.

    SomeViewController.m:

    - (void)setupNotifications
    {
        [[UIApplication sharedApplication] cancelAllLocalNotifications];
    
        // Read the notification type from the notification type picker view
        NSInteger row = [self.notificationTypePickerView selectedRowInComponent:0]; // Assumes there is only one component in the picker view.
        NSString *notificationType = [self.notificationList objectAtIndex:row]; // Where notificationList is the array storing the list of notification strings that appear in the picker view.
    
        // If the user has turned the sleep feature on (via the UISwitch):
        if (self.sleepToggleSwitch.on) {
            // Set the first notification to start after the user selected 'noNotificationPeriodEndDate' and repeat daily.
            // Add 1 hour to the notification date
            // Do while the notification date < the user selected 'noNotificationPeriodStartDate' ...
            //     Create the notification and set to repeat daily
            //     Add 1 hour to the notification date
            // Loop
        } else {
            // Set up 24 repeating daily notifications each one hour apart.
        }
    }
    

    请记住,一个应用最多只能创建64条通知(重复通知作为一个通知),因此,如果您希望在几天或几周内的不同时间触发通知,则可能需要重新考虑您的设计有点.

    Keep in mind that a single app can only create a maximum of 64 notifications (with repeating notifications counting as one) so, if you want notifications to fire at different times over a period of days or weeks, you might have to rethink your design a little.

    在NSUserDefaults中加载并存储用户选择的首选项:

    Load and store the user's chosen preferences in NSUserDefaults:

    SomeViewController.m:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        // Load the user defaults
        NSDate *sleepStartDate = [[NSUserDefaults standardUserDefaults] objectForKey:@"SleepStartDate"];
        self.notificationIgnoreStartTime.date = sleepStartDate ? sleepStartDate : [NSDate date];
        NSDate *sleepEndDate = [[NSUserDefaults standardUserDefaults] objectForKey:@"SleepEndDate"];
        self.notificationIgnoreEndTime.date = sleepEndDate ? sleepEndDate : [NSDate date];
        self.sleepToggleSwitch.on = [[NSUserDefaults standardUserDefaults] boolForKey:@"SleepEnabled"];
    
        // Watch for when the app leaves the foreground
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(applicationWillResignActive)
                                                     name:UIApplicationWillResignActiveNotification object:nil];
    }
    
    - (void)applicationWillResignActive
    {
        // If the timer is still waiting, fire it so the notifications are setup correctly before the app enters the background.
        if (self.userOptionInteractionTimer.isValid)
            [self.userOptionInteractionTimer fire];
    
        // Store the user's selections in NSUserDefaults
        [[NSUserDefaults standardUserDefaults] setObject:self.notificationIgnoreStartTime.date forKey:@"SleepStartDate"];
        [[NSUserDefaults standardUserDefaults] setObject:self.notificationIgnoreEndTime.date forKey:@"SleepEndDate"];
        [[NSUserDefaults standardUserDefaults] setBool:self.sleepToggleSwitch.on forKey:@"SleepEnabled"];
    }
    

    此外,请注意,如果应用即将进入后台(即离开前台)且计时器仍在计时,我们将强制其启动,以便在操作系统终止计时器之前设置通知.

    Also, notice above that if the app is about to enter the background (ie. leave the foreground) and the timer is still ticking, we force it to fire so the notifications are set up before the timer is killed by the OS.

    请记住,为所有日期选择器视图和所有IBAction以及代理和数据源为您的选择器视图连接代表IBAction.还记得设置代理和数据源方法,以便填充选择器视图.

    Remember to hook up the delegate IBActions for all your date picker views and all your IBActions as well as the delegates and data sources for your picker view. Also remember to setup your delegate and data source methods so the picker view is populated.

    就是这样!

    以上设计将确保无论应用是在前台,后台还是已终止,通知都会在正确的时间触发.(但是,如果在收到通知时应用程序处于前台,则用户将不会收到通知.而是将调用appDelegate上的 application:didReceiveLocalNotification:.)

    The above design will ensure that notifications get fired at the correct times whether or not the app is in the foreground, background or terminated. (However if the app is in the foreground when the notification is received, the user will not receive a notification. Instead, application:didReceiveLocalNotification: on the appDelegate will be called).

    显然,上面的代码不是可以执行的",但是您应该能够填补空白.

    Obviously the above code is not "execution-ready" but you should be able to fill in the gaps.

    这篇关于根据后台时间激活本地通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆