1

に保存されているスケジュール キャッシュがありNSDictionaryます。

以下の例では、20120 年 1 月 13 日 2:00PM2012 年 1 月 13 日 2:05PMのスケジュール時刻があります。これらの両方をキューに追加して、独自に起動するにはどうすればよいですか?

スケジュール キャッシュを構築します。

-(void) buildScheduleCache
{  
    NSCalendarDate *now = [NSCalendarDate calendarDate];

    NSFileManager *manager = [[NSFileManager defaultManager] autorelease];
    path = @"/var/mobile/Library/MobileProfiles/Custom Profiles";
    theProfiles = [manager directoryContentsAtPath:path];

    myPrimaryinfo = [[NSMutableArray arrayWithCapacity:6] retain];
    keys = [NSArray arrayWithObjects:@"Profile",@"MPSYear",@"MPSMonth",@"MPSDay",@"MPSHour",@"MPSMinute",nil];

    for (NSString *profile in theProfiles) 
    {
        plistDict = [[[NSMutableDictionary alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/%@",path,profile]] autorelease];

        [myPrimaryinfo addObject:[NSDictionary dictionaryWithObjects:
                                  [NSArray arrayWithObjects:
                                   [NSString stringWithFormat:@"%@",profile], 
                                   [NSString stringWithFormat:@"%@",[plistDict objectForKey:@"MPSYear"]], 
                                   [NSString stringWithFormat:@"%@",[plistDict objectForKey:@"MPSMonth"]], 
                                   [NSString stringWithFormat:@"%@",[plistDict objectForKey:@"MPSDay"]], 
                                   [NSString stringWithFormat:@"%@",[plistDict objectForKey:@"MPSHour"]], 
                                   [NSString stringWithFormat:@"%@",[plistDict objectForKey:@"MPSMinute"]],
                                   nil]forKeys:keys]];

        profileSched =
        [NSCalendarDate dateWithYear:[plistDict objectForKey:@"MPSYear"]
                               month:[plistDict objectForKey:@"MPSMonth"]
                                 day:[plistDict objectForKey:@"MPSDay"]
                                hour:[plistDict objectForKey:@"MPSHour"]
                              minute:[plistDict objectForKey:@"MPSMinute"]
                              second:01
                            timeZone:[now timeZone]];

        [self rescheduleTimer];
    }

    NSString *testPath = @"/var/mobile/Library/MobileProfiles/Schedules.plist";
    [myPrimaryinfo writeToFile:testPath atomically:YES];
}

イベントのスケジュール:

-(void) scheduleProfiles
{
    NSFileManager *manager = [[NSFileManager defaultManager] autorelease];
    path = @"/var/mobile/Library/WrightsCS/MobileProfiles/Custom Profiles";
    theProfiles = [manager contentsOfDirectoryAtPath:path error:nil];

    for (NSString *profile in theProfiles) 
    {
        NSMutableDictionary * plistDict = [[[NSMutableDictionary alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/%@",path,profile]] autorelease];

        profileSched =
        [NSCalendarDate dateWithYear:[[plistDict objectForKey:@"MPSYear"] intValue]
                               month:[[plistDict objectForKey:@"MPSMonth"] intValue]
                                 day:[[plistDict objectForKey:@"MPSDay"] intValue]
                                hour:[[plistDict objectForKey:@"MPSHour"] intValue]
                              minute:[[plistDict objectForKey:@"MPSMinute"] intValue]
                              second:01
                            timeZone:[NSTimeZone localTimeZone]];


            NSLog(@"DATE: %@      SCHEDULE: %@      PROFILE: %@",[NSDate date],profileSched,profile);
        if([NSDate date] < profileSched)
        {
            NSLog(@"IGNORING PROFILE: %@     WITH SCHEDULE: %@",profile,profileSched);
        }else{
            //Create the timer from the Cached Array
            schedTimer = [[NSTimer alloc] initWithFireDate:profileSched //[NSDate dateWithTimeIntervalSinceNow: 10]
                                                  interval:0.1f
                                                    target:self
                                                  selector:@selector(fireCustomProfile:)
                                                  userInfo:profile
                                                   repeats:NO];//[[plistDict objectForKey:@"MPSRepeat"] boolValue]];

            MLogString(@"Scheduling Profile: %@",profile);
            [[NSRunLoop currentRunLoop] addTimer:schedTimer forMode:NSDefaultRunLoopMode];
        }
    }
}

イベントを発生させる:

-(void)fireCustomProfile:(NSTimer *)timer
{   
    if([[NSDate date] earlierDate:[schedTimer fireDate]])
    {
        NSLog(@"Ignoring Profile: %@",[schedTimer userInfo]);
        return;
    }

    notify_post("com.wrightscs.MobileProfiles.setCustomProfile");
}

イベントの例:

<array>
    <dict>
        <key>MPSDay</key>
        <string>13</string>
        <key>MPSHour</key>
        <string>21</string>
        <key>MPSMinute</key>
        <string>15</string>
        <key>MPSMonth</key>
        <string>1</string>
        <key>MPSYear</key>
        <string>2012</string>
        <key>Profile</key>
        <string>Event 1</string>
        <key>Repeat</key>
        <true/>
    </dict>
</array>
<array>
    <dict>
        <key>MPSDay</key>
        <string>13</string>
        <key>MPSHour</key>
        <string>21</string>
        <key>MPSMinute</key>
        <string>20</string>
        <key>MPSMonth</key>
        <string>1</string>
        <key>MPSYear</key>
        <string>2012</string>
        <key>Profile</key>
        <string>Event 2</string>
        <key>Repeat</key>
        <true/>
    </dict>
</array>
4

3 に答える 3

4

本当にタイマーが必要ですか? タイマーは、アプリがアクティブな場合にのみアクティブになることに注意してください。アプリが非アクティブの場合は機能しません。遠い将来の任意の時点でアプリに何かを実行させようとしている場合、アプリを終了するたびにすべてのタイマーが停止するため、タイマーでは問題を解決できません。

(1) アプリがアクティブなときにイベントのタイマーを設定したいだけで、(2) キューに常に不明な数のイベントがある場合、最大の問題は、任意の数のイベントをターゲットにする方法を整理することです。任意の数のイベントのタイマー。

幸いなことに、タイマーはプロパティに任意userInfoのオブジェクトを渡すことができるため、すべてのイベントをオブジェクトにラップして、そのオブジェクトをタイマーに渡します。次に、タイマー起動メソッドがイベントを抽出し、それに基づいて動作できます。

このようなもの:

// assume a data model with event objects with the attributes and methods shown

- (void) setTimerForEvent:(EventClass *) anEvent{
    [NSTimer timerWithTimeInterval:[anEvent eventTimeFromNow] 
                            target:self 
                          selector:@selector(fireEvent:) 
                          userInfo:anEvent 
                           repeats:NO];

}//------------------------------------setTimerForEvent:------------------------------------

- (void)fireEvent:(NSTimer*)theTimer{
    [self handleEvent:(EventClass *)theTimer.userInfo]; 
    [theTimer invalidate];
}//------------------------------------fireEvent:------------------------------------

メソッドが呼び出されてからイベントが発生するまでの残り秒数の-[EventClass eventTimeFromNow]NSTimerInterval を返す必要があります。

于 2010-04-16T17:44:55.203 に答える
3

NSTimer の代わりに UILocalNotification を使用できます。制限は、ユーザーの操作なしではアプリケーションにアクションがないことですが、アプリがシャットダウンされた場合でも通知がトリガーされることです。

UILocalNotificationsに関する Apple のドキュメント:

UILocalNotification のインスタンスは、アプリケーションが特定の日時にユーザーに表示するようにスケジュールできる通知を表します。オペレーティング システムは、適切なタイミングで通知を配信する責任があります。これが発生するために、アプリケーションが実行されている必要はありません。

...

システムがローカル通知を配信すると、アプリケーションの状態と通知の種類に応じて、いくつかのことが発生する可能性があります。アプリケーションが最前面に表示されていない場合、システムは警告メッセージを表示し、アプリケーションにバッジを付け、サウンドを再生します (通知で指定されているものは何でも)。通知がアラートで、ユーザーがアクション ボタンをタップすると (または、デバイスがロックされている場合は、アクション スライダーをドラッグして開くと)、アプリケーションが起動します。application:didFinishLaunchingWithOptions: メソッドでは、アプリケーション デリゲートは UIApplicationLaunchOptionsLocalNotificationKey キーを使用して、渡されたオプション ディクショナリから UILocalNotification オブジェクトを取得できます。デリゲートは通知のプロパティを調べることができ、通知の userInfo ディクショナリにカスタム データが含まれている場合は、そのデータにアクセスし、それに応じて処理できます。一方、ローカル通知がアプリケーション アイコンにバッジを付けるだけで、それに応答してユーザーがアプリケーションを起動した場合、application:didFinishLaunchingWithOptions: メソッドが呼び出されますが、オプション ディクショナリには UILocalNotification オブジェクトは含まれません。

システムが通知を配信するときにアプリケーションが最前面に表示されている場合、アラートは表示されず、アイコンもバッジも表示されず、サウンドも再生されません。ただし、 application:didReceiveLocalNotification: は、アプリケーション デリゲートが実装している場合に呼び出されます。UILocalNotification インスタンスがこのメソッドに渡され、デリゲートはそのプロパティをチェックしたり、userInfo ディクショナリから任意のカスタム データにアクセスしたりできます。

ここで、主なアイデアが次のような優れたチュートリアルを見つけることができます。

通知設定:

Class cls = NSClassFromString(@"UILocalNotification");
if (cls != nil) {
    UILocalNotification *notif = [[cls alloc] init];
    notif.fireDate = [datePicker date];
    notif.timeZone = [NSTimeZone defaultTimeZone];

    notif.alertBody = TEXT;
    notif.alertAction = LAUNCH_BUTTON;
    notif.soundName = UILocalNotificationDefaultSoundName;
    notif.applicationIconBadgeNumber = NOTIFICATIONS_REMAINING;

    NSDictionary *userDict = [NSDictionary dictionaryWithObject:CUSTOM_INFO 
                                            forKey:kRemindMeNotificationDataKey];
    notif.userInfo = userDict;

    [[UIApplication sharedApplication] scheduleLocalNotification:notif];
    [notif release];
}

アプリケーションが実行されていないときの通知の処理 (アプリケーション デリゲート内):

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

    Class cls = NSClassFromString(@"UILocalNotification");
    if (cls) {
        UILocalNotification *notification = [launchOptions objectForKey:
                        UIApplicationLaunchOptionsLocalNotificationKey];

        if (notification) {
            NSString *reminderText = [notification.userInfo 
                        objectForKey:kRemindMeNotificationDataKey];
           [viewController showReminder:reminderText];
        }
    }

    application.applicationIconBadgeNumber = NOTIFICATIONS_REMAINING_LESS_ONE;

    [window addSubview:viewController.view];
    [window makeKeyAndVisible];

    return YES;
}

フォアグラウンドでのアプリケーション (アプリケーション デリゲート内):

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {

    UIApplicationState state = [application applicationState];
    if (state == UIApplicationStateInactive) {
        // Application was in the background when notification
        // was delivered.
    }
}
于 2012-01-19T01:08:37.317 に答える
0

イベントごとにタイマーが必要です。timerたぶん、変数にタイマーを割り当てないでください。これらのタイマーを作成して、で解放するだけtheFireEventです。ただし、そのセレクターをに変更し@selector(theFireEvent)、メソッドにシグネチャがあることを確認する必要があります。

- (void)timerFireMethod:(NSTimer*)theTimer

于 2010-04-13T20:55:22.040 に答える