虽然 NSOperation
和 NSOperationQueue
对于某些重复性问题表现良好,而 NSInvocation
对于其他问题表现良好,但 iOS 并没有提供一套易于管理大量任意后台任务的工具。PPQueue 提供了一个高级接口,用于使用 GCD 和 SQLite3 实现线程作业队列。您需要做的只是处理提供的代理方法中的作业,其余的由 PPQueue 处理。
开始使用 PPQueue 的最简单方法是查看所包含的示例应用程序。XCode 项目文件可以在 PPQueueDemo > PPQueueDemo.xcodeproj
中找到。
PPQueue 需要使用 libsqlite3.0.dylib
和 FMDB 作为存储引擎。与以往一样,处理所有这些细节的最快方法是使用 CocoaPods。PPQueue 作为单例实现,以便在任何地方创建作业。但是,所有任务都通过单个代理方法进行处理,因此通常在应用程序代理中设置 PPQueue 是最有意义的。
YourAppDelegate.h
#import "PPQueue.h"
@interface YourAppDelegate : UIResponder <UIApplicationDelegate, PPQueueDelegate>
YourAppDelegate.m
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[PPQueue sharedInstance].delegate = self;
[PPQueue sharedInstance].retryLimit = 3; // or what ever you need
[[PPQueue sharedInstance] start];
}
- (void)applicationWillResignActive:(UIApplication *)application
{
[[PPQueue sharedInstance] stop];
}
- (PPQueueResult)queue:(PPQueue *)queue processJob:(NSDictionary *)job
{
// demonstrate a failing task (eg. sending some data to server fails
if ([@"myFailingTask" isEqualToString:job[@"task"]]) {
NSLog(@"myFailingTask: %@", job[@"data"]);
// Process your data
// ...
//Optionally stop the queue processing and then restart it when network connection is ok
//[[PPQueue sharedInstance] stop];
return PPQueueResultFail;
}
else {
NSLog(@"%@: %@", job[@"task"], job[@"data"]);
// Process your data
// ...
}
return PPQueueResultSuccess;
}
SomewhereElse.m
NSDictionary *data1 = @{ @"key": @"data1", @"value": @(1)};
NSDictionary *data2 = @{ @"key": @"data2", @"value": @(2)};
NSDictionary *data3 = @{ @"key": @"data3", @"value": @(3)};
// enqueue some data
[[PPQueue sharedInstance] enqueueWithData:data1 forTask:@"myTask" withPriority:2];
[[PPQueue sharedInstance] enqueueWithData:data2 forTask:@"myFailingTask" withPriority:2];
[[PPQueue sharedInstance] enqueueWithData:data3 forTask:@"myHighPrioTask" withPriority:1];
为了简化,代理方法期望返回 PPQueueResult
类型,该类型允许三个不同的状态
PPQueueResultSuccess
:用于表示作业已成功完成PPQueueResultFail
:用于表示作业失败并应重试(最多到指定的 retryLimit
)PPQueueResultCritical
:用于表示作业失败临界且不应再次尝试PPQueue 包含一个适合处理异步作业(如 HTTP 请求或磁盘 I/O)的代理方法。
- (void)queue:(PPQueue *)queue processJob:(NSDictionary *)job completion:(void (^)(PPQueueResult))block
{
@try {
if ([[job objectForKey:@"task"] isEqualToString:@"success"]) {
block(PPQueueResultSuccess);
} else if ([[job objectForKey:@"task"] isEqualToString:@"fail"]) {
block(PPQueueResultFail);
} else {
block(PPQueueResultCritical);
}
}
@catch (NSException *exception) {
block(PPQueueResultCritical);
}
}
PPQueue 包含一系列方法,用于帮助对特定于每个任务的任务队列进行反射。
- (Boolean)jobExistsForTask:(NSString *)task;
- (Boolean)jobIsActiveForTask:(NSString *)task;
- (NSDictionary *)nextJobForTask:(NSString *)task;
- (void)enqueueWithData:(id)data forTask:(NSString *)task;
- (void)enqueueWithData:(id)data forTask:(NSString *)task withPriority:(NSUInteger)priority;
- (void)start;
- (void)stop;
- (void)empty;
- (Boolean)jobExistsForTask:(NSString *)task;
- (Boolean)jobIsActiveForTask:(NSString *)task;
- (NSDictionary *)nextJobForTask:(NSString *)task;
/**
* Removes all jobs older than the time interval.
* @param {NSString} a sqlite time interval (e.g '-1 day' or '-3 months')
*/
- (void)removeOldJobs:(NSString*)timeInterval;
- (PPQueueResult)queue:(PPQueue *)queue processJob:(NSDictionary *)job;
- (void)queue:(PPQueue *)queue processJob:(NSDictionary *)job completion:(void (^)(PPQueueResult result))block;
PPQueueResultSuccess
PPQueueResultFail
PPQueueResultCritical
@property (weak) id<PPQueueDelegate> delegate;
@property (readonly) Boolean isRunning;
@property (readonly) Boolean isActive;
@property NSUInteger retryLimit;
PPQueueDidStart
PPQueueDidStop
PPQueueDidDrain
PPQueueJobDidSucceed
PPQueueJobDidFail
PPQueue 是为 iOS 5 及以上版本设计的。
PPQueue 使用 ARC 构建。如果你的项目未使用 自动引用计数 (ARC),你需要为 PPQueue 所有源文件设置 -fobjc-arc
编译器标志。要在 Xcode 中这样做,请转到您的活动目标并选择“编译阶段”标签。现在选择所有 PPQueue 源文件,按 Enter 键,插入 -fobjc-arc
,然后单击“完成”以启用 PPQueue 的 ARC。