测试已测试 | ✓ |
Lang语言 | Obj-CObjective C |
许可证 | MIT |
发布最新版本 | 2015年7月 |
由 zackliston 维护。
依赖项 | |
FMDB | = 2.4 |
Reachability | = 3.2 |
在 Objective-C 中调度工作有很多种方式,从 Grand Central Dispatch 到 NSOperations,然而,没有一个方法能够处理持久化工作。ZLTaskManager 填补了这一空白。使用这个库,我们可以从应用启动到应用启动来持久化工作。我们可以确保这项工作会无休止地重试,直到成功(或者直到我们决定停止重试,后面会详细讨论)。正因为如此,我们可以在不添加无穷无尽的保险措施以确保其正确完成的情况下开始工作。
ZLTaskManager 有四个主要类:
1: ZLTaskManager
- 负责排队、停止、取消、重启等所有工作。
2: ZLTask
- 用于在 TaskManager
上指定和排队工作
3: ZLTaskWorker
- 实际工作的位置。您必须在 ZLTaskWorker
的子类中提供-custom implementation of your work。
3: ZLManager
- 负责管理 TaskWorkers
。 TaskManager
将请求这个子类的子类根据其注册的任务类型来创建 TaskWorkers
。
ZLTaskManager
是一个共享实例,并首次调用时进行初始化。建议在应用启动时初始化 TaskManager
并注册所有可用的 ZLManager
子类,例如
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
ZLManagerSubclass *yourManager = [ZLManagerSubclass new];
[ZLTaskManager sharedInstance] registerManager:yourManager forTaskType:@"your.task.type"];
}
一旦为某种特定任务类型注册了管理器,TaskManager
将自动启动所有已排队且未完成的工作。
注意 一个 ZLManager
可以注册多个任务类型,但每种任务类型只能注册一个管理器。
工作是以 ZLTasks
的形式指定的,然后排队在 TaskManager
上。一个 ZLTask
是您指定任务的所有内容的方式,包括优先级、网络需求、如果失败应该重试的次数(可能无限)。然而,最重要有两点信息
taskType
- 这是一个定义任务类型的字符串。它被 TaskManager
使用,以确定为此任务使用哪个 ZLManager
和 ZLTaskWorker
子类。jsonData
- 这是一个兼容JSON的NSDictionary(仅限于NSNumbers,NSString,NSArray和其他NSDictionaries)。您使用它来传递完成任务所需的所有信息。您需要为您自己的ZLTaskWorker
子类编程,以便理解和适当地从这个字典中提取信息。这是创建和排队工作的方式
// This should be a constant defined somewhere.
NSString *taskType = @"test.task.type";
NSDictionary *jsonData = @{@"urlToFetch":@"www.example.com/fetch", @"urlToPost":@"www.example.com/post", @"someNumber":@1, @"someParameters":@[@"one", @"two",@"three"]}
ZLTask *task = [[ZLTask alloc] initWithTaskType:taskType jsonData:jsonData];
task.requiresInternet = YES;
task.majorPriority = 10000;
[[ZLTaskManager sharedInstance] queueTask:task];
所有工作都在您的ZLTaskWorker
子类中完成。为了了解如何实施您的TaskWorker
,请访问这个页面.
您的TaskWorker
是由您为该任务类型注册的ZLManager
子类创建的。您必须在您的Manager
类中重写taskWorkerForWorkItem:
方法。下面是一个例子
- (ZLTaskWorker *)taskWorkerForWorkItem:(ZLInternalWorkItem *)workItem
{
//This should be defined as a constant somewhere
NSString *taskType = @"test.task.type";
ZLTaskWorker *taskWorker;
if ([workItem.taskType isEqualToString:taskType]) {
taskWorker = [ZLTaskWorkerSubclass new];
} else if ([workItem.taskType isEqualToString:@"otherTaskTypeManagerHandles"]) {
taskWorker = [ZLOtherTaskWorkerSubclass new];
} else
// If your Manager is registered for a task type you MUST handle it. This line of code should never execute
// if you are implementing this correctly. It is recommended to log here in case this happens so you
// know what's going wrong.
NSLog(@"Manager is not handling task type %@", workItem.taskType);
}
// Required
[taskWorker setupWithWorkItem:workItem];
return taskWorker;
}
为了防止iOS在应用程序即将终止时停止正在运行中的进程(以及您的应用特定的需求),我们必须停止我们的工作。有两种方式可以做到这一点:异步或同步。请参阅此页面获取更多详细信息。您必须在您的应用程序代理中的applicationWillTerminate
方法中实现以下代码
- (void)applicationWillTerminate:(UIApplication *)application
{
// This is a synchronous method.
[[ZLTaskManager sharedInstance] stopAndWaitWithNetworkCancellationBlock:^{
// Cancel any network tasks your task workers may be using so that the cancellation process
// is not waiting on them to finish.
}];
}
如果您决定不启用后台执行,那么每次您的应用程序进入后台时都必须停止工作,并在每次进入前台时重新启动它,如下所示
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// This is a synchronous method.
[[ZLTaskManager sharedInstance] stopAndWaitWithNetworkCancellationBlock:^{
// Cancel any network tasks your task workers may be using so that the cancellation process
// is not waiting on them to finish.
}];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[ZLTaskManager sharedInstance] resume];
}
如果您决定在您的应用程序中为ZLTaskManager
启用后台执行,那么每次您的应用程序进入后台时都必须启动一个后台任务,并确保它每次应用程序变得活跃时都再次启动
- (void)applicationDidEnterBackground:(UIApplication *)application
{
if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]) {
if ([[UIDevice currentDevice] isMultitaskingSupported]) {
__block UIBackgroundTaskIdentifier backgroundTask;
backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^{
[[ADTaskManager sharedInstance] stopAndWait];
NSLog(@"ZLTaskManager background tasks ran out of time. Stopping");
[application endBackgroundTask:backgroundTask];
backgroundTask = UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
//This is a blocking method. It shouldn't be called anywhere but in this context
[ZLTaskManager waitForTasksToFinishOnSharedInstance];
NSLog(@"ZLTaskManager finished background tasks");
[application endBackgroundTask:backgroundTask];
backgroundTask = UIBackgroundTaskInvalid;
});
}
}
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[ZLTaskManager sharedInstance] resume];
}