views:

205

answers:

3

I have a schedule cache stored in a pList.

For the example below, I have a schedule time of April 13, 2010 2:00PM and Aril 13, 2010 2:05PM. How can I add both of these to a queue to fire on their own?

item 0
-Hour
--14
-Minute
--00
-Month
--04
-Day
--13
-Year
--2010

item 1
-Hour
--14
-Minute
--05
-Month
--04
-Day
--13
-Year
--2010

this is how I am attempting to schedule multiple events to fire at specific date / time.

-(void) buildScheduleCache
{
MPNotifyViewController *notifier = [MPNotifyViewController alloc] ;
[notifier setStatusText:@"Rebuilding schedule cache, this will only take a moment."];
[notifier show];


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) rescheduleTimer
{
timer = [[NSTimer alloc] initWithFireDate:profileSched
                                 interval:0.0f
                                   target:self
                                 selector:@selector(theFireEvent)
                                 userInfo:nil
                                  repeats:YES];

NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
}
A: 

You'll need a timer for each event. Maybe don't assign the timer to the timer variable. You can just create these timers and release them in the theFireEvent. You'll need to change that selector to @selector(theFireEvent) though, and make sure the method has the signature:

- (void)timerFireMethod:(NSTimer*)theTimer

half_brick
well, what if I have an unknown number of schedules to be queued? how can I create a new timer for each?
AWright4911
Well your call to rescheduleTimer is within the loop that reads from the plist for profiles (if I'm understanding your code correctly), so it should get called once per profile it reads and create a timer each time.Also, I think you're currently leaking memory, as you're re-allocing new timers into the timer variable, but never releasing them. You want those timers to hang around until they fire, after which you want to release them. So it probably makes sense to put a release in the timer event.
half_brick
+2  A: 

Are you sure a timer is what you want? Remember, a timer is only active when your app is active. It does not work when the app is inactive. If you're trying to get your app to do something at any time in the distant future, a timer will not really solve your problem because every time you quit the app, all its timers die.

Assuming that (1) you do just want to set timers for events while the app is active and (2) you always have an unknown number of events in the queue, then your biggest problem will be sorting out how to target an arbitrary number of timers for an arbitrary number of events.

Fortunately, timers can pass any arbitrary object in their userInfo property so you want to wrap every event in an object and pass that object to the timer. Then the timer fired method can extract the event and act on it.

Something like this:

// 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:------------------------------------

The -[EventClass eventTimeFromNow] should return a NSTimerInterval of the seconds remaining between the time the method is called and time of the event.

TechZen
Technically this is for a dylib that is constantly running in the background (non-AppStore) and I need the timer to grab each date in my arrays and set a timer (or whatever) for every date to fire on the date.
AWright4911
This approach will work for what you want. There is not time limit on on timers. In principle, you can start a timer to fire years down the line if the system keeps up that long. You just need to wrap the dates in a class so they can be passed by the timer. You could pass the raw dates but then you might know what to do with them. A more descriptive Event type class would be better.
TechZen
A: 

After some testing, I finnaly got the scheduling system to work! Where I went wrong was in how I was reading the dates from the saved files, but that is all fixed now!

AWright4911