Pianificare più, gli eventi quotidiani con NSTimer?
-
26-09-2019 - |
Domanda
Ho una cache programma memorizzato in una NSDictionary
.
Per l'esempio riportato di seguito, ho un tempo di programma di 13 gennaio 20120 14:00 e 13 Gennaio 2012 02:05 . Come posso aggiungere entrambi questi a una coda di fuoco da soli?
Sviluppare Schedulazione cache:
-(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];
}
pianificare l'evento:
-(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];
}
}
}
Fuoco l'evento:
-(void)fireCustomProfile:(NSTimer *)timer
{
if([[NSDate date] earlierDate:[schedTimer fireDate]])
{
NSLog(@"Ignoring Profile: %@",[schedTimer userInfo]);
return;
}
notify_post("com.wrightscs.MobileProfiles.setCustomProfile");
}
Esempio evento:
<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>
Soluzione
È possibile utilizzare al posto di UILocalNotification NSTimer. Le limitazioni sono che non ci sono azioni nella vostra applicazione senza la vostra interazione, ma ci viene attivato una notifica anche se l'applicazione è shutted verso il basso.
Documentazione di Apple su UILocalNotifications :
Le istanze di UILocalNotification rappresentano le notifiche che un applicazione può programmare per la presentazione ai propri utenti a specifiche date e orari. Il sistema operativo è responsabile della consegna la notifica al momento opportuno; l'applicazione non ha bisogno di essere in esecuzione perché questo avvenga.
...
Quando il sistema fornisce una notifica locale, diverse cose possono accadere, a seconda dello stato di applicazione e il tipo di notifica. Se l'applicazione non è in primo piano e visibile, la sistema visualizza il messaggio di avviso, distintivi l'applicazione, e svolge un sound-tutto ciò che è specificata nella notifica. Se la notifica è un allarme e l'utente tocca il pulsante di azione (o, se il dispositivo è bloccato, trascina il cursore aperto azione), l'applicazione viene avviata. Nel l'applicazione: didFinishLaunchingWithOptions: Metodo di applicazione delegato può ottenere l'oggetto UILocalNotification dal passato in Opzioni di dizionario con la chiave UIApplicationLaunchOptionsLocalNotificationKey. La lattina delegato ispezionare le proprietà della notifica e, se la notifica include dati personalizzati nel suo dizionario userInfo, si può accedere a quel i dati ed elaborare di conseguenza. D'altra parte, se il locale la notifica badge solo l'icona dell'applicazione, e l'utente in lanci di risposta l'applicazione, la applicazione: didFinishLaunchingWithOptions: metodo viene richiamato, ma non oggetto UILocalNotification è inclusa nel dizionario opzioni.
Se l'applicazione è più importante e visibile quando il sistema eroga la notifica, nessun avviso viene visualizzato, nessuna icona è targate, e nessun suono è giocato. Tuttavia, l'applicazione: didReceiveLocalNotification: è chiamato se il delegato applicazione implementa. Il esempio UILocalNotification viene passato in questo metodo, e la delegato può controllare le proprietà o accedere ai dati personalizzati dal userInfo dizionario.
È possibile trovare un buon tutorial qui dove l'idea principale è simile a questo:
Il setup di notifica:
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];
}
Cura dello nofitication quando l'applicazione non è in esecuzione (nel delegato applicaction):
- (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;
}
Applicazione in primo piano (nel delegato applicaction):
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateInactive) {
// Application was in the background when notification
// was delivered.
}
}
Altri suggerimenti
Sei sicuro un timer è quello che vuoi? Ricordate, un timer è attiva solo quando la vostra applicazione è attiva. Non funziona quando l'applicazione non è attiva. Se si sta cercando di ottenere la vostra applicazione di fare qualcosa in qualsiasi momento, in un lontano futuro, un timer non sarà davvero risolvere il problema, perché ogni volta che si esce l'applicazione, tutte le sue timer morire.
Supponendo che (1) si vuole solo per i timer impostati per gli eventi, mentre l'applicazione è attiva e (2) si ha sempre un numero imprecisato di eventi nella coda, allora il vostro problema più grande sarà smistamento come indirizzare un numero arbitrario di temporizzatori per un numero arbitrario di eventi.
Per fortuna, i timer può passare qualsiasi oggetto arbitrario nella loro proprietà userInfo
così si vuole avvolgere ogni evento in un oggetto e passare l'oggetto al timer. Metodo Poi il timer sparato può estrarre l'evento e agire su di esso.
Qualcosa di simile a questo:
// 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:------------------------------------
Il -[EventClass eventTimeFromNow]
deve restituire un NSTimerInterval dei secondi rimanenti tra il momento in cui il metodo viene chiamato e ora dell'evento.
Avrete bisogno di un timer per ogni evento.
Forse non assegnare il timer alla variabile timer
. Si può solo creare questi timer e rilasciarli nel theFireEvent
. Avrete bisogno di cambiare la situazione selettore per @selector(theFireEvent)
, però, e assicurarsi che il metodo ha la firma:
- (void)timerFireMethod:(NSTimer*)theTimer