使用 NSTimer 安排多个每日活动?
我有一个存储在 NSDictionary
中的计划缓存。
对于下面的示例,我的计划时间为 20120 年 1 月 13 日下午 2:00 和 2012 年 1 月 13 日下午 2:05。我如何将这两个添加到队列中以自行触发?
构建计划缓存:
-(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>
I have a schedule cache stored in an NSDictionary
.
For the example below, I have a schedule time of January 13, 20120 2:00PM and January 13, 2012 2:05PM. How can I add both of these to a queue to fire on their own?
Build the Schedule 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];
}
Schedule The Event:
-(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];
}
}
}
Fire the Event:
-(void)fireCustomProfile:(NSTimer *)timer
{
if([[NSDate date] earlierDate:[schedTimer fireDate]])
{
NSLog(@"Ignoring Profile: %@",[schedTimer userInfo]);
return;
}
notify_post("com.wrightscs.MobileProfiles.setCustomProfile");
}
Example Event:
<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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您确定计时器是您想要的吗?请记住,计时器仅在您的应用程序处于活动状态时才处于活动状态。当应用程序处于非活动状态时,它不起作用。如果您试图让您的应用程序在遥远的将来的任何时间执行某些操作,计时器并不能真正解决您的问题,因为每次您退出应用程序时,它的所有计时器都会消失。
假设 (1) 您只想在应用程序处于活动状态时为事件设置计时器,并且 (2) 队列中始终有未知数量的事件,那么您最大的问题将是弄清楚如何定位任意数量的事件任意数量事件的计时器。
幸运的是,计时器可以在其
userInfo
属性中传递任意对象,因此您希望将每个事件包装在一个对象中并将该对象传递给计时器。然后计时器触发的方法可以提取事件并对其采取行动。像这样的:
-[EventClass eventTimeFromNow]
应该返回调用方法的时间和事件发生时间之间剩余秒数的 NSTimerInterval。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:
The
-[EventClass eventTimeFromNow]
should return a NSTimerInterval of the seconds remaining between the time the method is called and time of the event.您可以使用 UILocalNotification 代替 NSTimer。限制是,如果没有您的交互,应用程序中不会执行任何操作,但即使应用程序关闭,也会触发通知。
有关 UILocalNotifications:
您可以在此处 主要思想是这样的:
通知设置:
当应用程序未运行时处理通知(在应用程序委托中):
应用程序在前台(在应用程序委托中):
You can use UILocalNotification instead of NSTimer. The limitations are that there is no actions in your application without your interaction, but there is triggered a notification even if the app is shutted down.
Apple documentation about UILocalNotifications:
You can found a good tutorial here where the main idea is like this:
The notification setup:
Handling the nofitication when the application is not running (in the applicaction delegate):
Application in the foreground (in the applicaction delegate):
每个事件都需要一个计时器。
也许不要将计时器分配给
timer
变量。您只需创建这些计时器并在theFireEvent
中释放它们即可。不过,您需要将该选择器更改为@selector(theFireEvent)
,并确保该方法具有签名:- (void)timerFireMethod:(NSTimer*)theTimer
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 thetheFireEvent
. You'll need to change that selector to@selector(theFireEvent)
though, and make sure the method has the signature:- (void)timerFireMethod:(NSTimer*)theTimer