2

そのため、繰り返し間隔のローカル通知を含むアプリがあり、スリープ時間中に通知を一時停止する機能を追加したいと考えています。

これまでのところ、ユーザーが繰り返し間隔を停止したい時刻と自動的に再起動する時刻を指定するための 2 つの日付ピッカーを作成しました。そして、スリープモードを有効にするか、機能を無視するための uiswitch を追加しました。

さて、メインの uipickerview を作成するにはどうすればよいでしょうか?(彼らはここから通知を選択します) - uiswitch がオンの場合にリッスンし、最初の datepicker からの通知を一時停止し、通知を再開します2番目の日付ピッカーから来る時間?

私はすでに日付ピッカーと uiswitch をセットアップしましたが、uipickerview でそれを実装する方法がわかりません..DidSelectRow のメソッドの下にある必要がありますか? またはappdelegateのメソッド(DidEnterBackgroundなど)?

アイデアを理解し、私を助けるために、さらに情報やコードが必要かどうか尋ねてください. ありがとう。

拡張機能:

日付ピッカー用に準備したコードを次に示しますが、ピッカー ビューに適切に追加するための接続が不足しています。

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);

時間を比較するための次のコードもあります。

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

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

2 に答える 2

2

iOS では、特定の 2 つの日付/時間の間にローカルで繰り返し通知を投稿することはサポートされていません。さらに、地理ベースの通知とは異なり、フォアグラウンドにない場合、アプリは起動された通知のアラートを受けません。そのため、ユーザーが眠っていない時間に個別の通知を多数作成することで、これを回避する必要があります。

次の手順に従って、基本的なソリューションを作成します。

  1. ビュー コントローラーのヘッダーでコントロールを IBOutlets に接続します。

    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
    
  2. IBAction メソッドを作成し、View Controller の実装ファイルで各コントロール (2 つの UIDatePicker、1 つの UISwitch、1 つの 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];
    }
    
  3. プライベート メソッドではstartUserOptionInteractionTimer、NSTimer を (再) 開始します。ここではタイマーを使用して、ユーザーが日付を変更したり、スイッチをすばやく切り替えたりした場合 (おそらくそうする可能性があります)、通知を次々と破棄してセットアップすることを回避します。(NSTimer プロパティuserOptionInteractionTimerは、実装ファイルのインターフェイス継続で宣言する必要があります)。

    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];
    }
    
  4. 別のプライベート メソッドを作成して、既存の通知を破棄し、新しい通知をセットアップします。

    ここでの通知の設定は、ユーザーに通知する期間と頻度によって異なります。1 時間ごとにユーザーに通知する必要があり、ユーザーが睡眠機能を有効にしている場合、毎日繰り返される 1 時間ごとに (ユーザーの睡眠時間に応じて) 14 ~ 18 個の通知をセットアップします。

    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.
        }
    }
    

    1 つのアプリで作成できる通知は最大 64 個までです (通知の繰り返しは 1 回としてカウントされます)。そのため、数日または数週間にわたって異なるタイミングで通知を発生させたい場合は、設計を再考する必要があるかもしれません。少し。

  5. ユーザーが選択した設定を読み込み、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"];
    }
    

    また、アプリがバックグラウンドに入ろうとしている (つまり、フォアグラウンドを離れている) ときにタイマーがまだカチカチ音をたてている場合は、OS によってタイマーが強制終了される前に通知が設定されるように強制的に起動することに注意してください。

  6. すべての日付ピッカー ビューとすべての IBActions のデリゲート IBActions と、ピッカー ビューのデリゲートとデータ ソースを接続することを忘れないでください。また、デリゲート メソッドとデータ ソース メソッドをセットアップして、ピッカー ビューにデータが取り込まれるようにすることも忘れないでください。

  7. それでおしまい!

上記の設計により、アプリがフォアグラウンド、バックグラウンド、または終了されているかどうかに関係なく、通知が正しいタイミングで発生することが保証されます。(ただし、通知を受信したときにアプリがフォアグラウンドにある場合、ユーザーは通知を受信しません。代わりapplication:didReceiveLocalNotification:に、appDelegate で呼び出されます)。

明らかに、上記のコードは「実行可能」ではありませんが、ギャップを埋めることができるはずです。

于 2013-04-11T09:56:48.060 に答える
1

は、どこでもチェックできるまたは のUISwitch属性を設定し、おそらくピッカー (userInteractionEnabled など) をアクティブ化および非アクティブ化します。plistNSUserDefaults

また、常にステータスを切り替えることができるようにUISwitchIBActionメソッドと接続します。ValueChanged

さらに、時間を更新するためだけのDidSelectRowAtIndexPath:方法を使用します(複数の場所に必要な場合は、それらを保存することもできます。またはUIPickerView、属性をクラス属性(静的)として使用します^^plistNSUserDefaults

NSTimer自動的にチェックするために、60秒で循環的に実行されるaを使用し、AppDelegate続行または戻ることができるかどうか自体をチェックするイベントを発生させるか、それを発生させたい場合はすでにここでチェックします(イベントを発生させていることを確認するために拡張できます)分のどこかではなく、00 秒)。
発砲できるかどうかを確認するためのサンプルは、状態に対して次のようになります。

startSilentTimePicker : 午後 10 時 30 分
stopSilentTimePicker : 午前 7 時 15 分
activitySwitch : オン

// filtered date by only time
NSDateComponents *startComps = [[NSCalendar currentCalendar] components:NSHourCalendarUnit|NSMinuteCalendarUnit fromDate:[startSilentTimePicker date]];
NSDateComponents *endComps = [[NSCalendar currentCalendar] components:NSHourCalendarUnit|NSMinuteCalendarUnit fromDate:[stopSilentTimePicker date]];
NSDateComponents *currentComps = [[NSCalendar currentCalendar] components:NSHourCalendarUnit|NSMinuteCalendarUnit fromDate:[NSDate date]];

if([[startComps date] laterDate:[currentComps date]] == [currentComps date] || 
[[endComps date] earlierDate:[currentComps date]] == [currentComps date])
{
    // set the value, that tells you beeing in silent time, set a return from the methode or invert to fire notification here
}

私のコードで実際にテストしていませんが、似たようなものを使用しています。何か不足している場合は、教えてください。多分私は完了することができます ;)

于 2013-04-09T07:03:02.683 に答える