我开发了一个类别,它使NSOperation能够以定时间隔在后台执行。我真的很感激收到一些反馈意见,尤其是这种方法的任何潜在问题,我都没有想到。
谢谢!
以下是代码:
的NSOperation + Repeat.h
#import <Foundation/Foundation.h>
@interface NSOperation (repeat)
@property (readonly, nonatomic) NSTimeInterval repeatInterval;
@property (readonly, nonatomic) NSOperationQueue *repeatOperationQueue;
- (void)performUsingOperationQueue:(NSOperationQueue *)operationQueue;
- (void)performAtRepeatingInterval:(NSTimeInterval)interval usingOperationQueue:(NSOperationQueue *)operationQueue;
@end
的NSOperation + Repeat.m
#import "NSOperation+repeat.h"
#import <objc/runtime.h>
static char const * const RepeatPropertiesKey = "RepeatProperties";
@implementation NSOperation (repeat)
@dynamic repeatInterval;
@dynamic repeatOperationQueue;
static NSString * RepeatIntervalKey = @"interval";
static NSString * RepeatOperationQueueKey = @"operationQueue";
static NSString * RepeatTimerKey = @"timer";
- (NSMutableDictionary *)repeatProperties {
NSMutableDictionary * properties = objc_getAssociatedObject(self, RepeatPropertiesKey);
if (properties == nil) {
properties = [NSMutableDictionary new];
objc_setAssociatedObject(self, RepeatPropertiesKey, properties, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return properties;
}
- (NSTimeInterval)interval {
NSNumber * interval = [[self repeatProperties] objectForKey:RepeatIntervalKey];
return [interval doubleValue];
}
- (NSOperationQueue *)repeatOperationQueue {
NSOperationQueue * operationQueue = [[self repeatProperties] objectForKey:RepeatOperationQueueKey];
return operationQueue;
}
- (void)performUsingOperationQueue:(NSOperationQueue *)operationQueue {
[operationQueue addOperation:[self copy]];
}
- (void)performAtInterval:(NSTimer *)timer {
[self performUsingOperationQueue:self.repeatOperationQueue];
}
- (void)performAtRepeatingInterval:(NSTimeInterval)interval usingOperationQueue:(NSOperationQueue *)operationQueue {
// Save interval and operationQueue in repeatProperties
[self.repeatProperties setValue:[NSNumber numberWithDouble:interval] forKey:RepeatIntervalKey];
[self.repeatProperties setValue:operationQueue forKey:RepeatOperationQueueKey];
// Create timer to call performAtInterval on self
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:(interval*60)
target:self
selector:@selector(performAtInterval:)
userInfo:nil
repeats:YES];
// Save the timer in repeatProperties
[self.repeatProperties setValue:timer forKey:RepeatTimerKey];
[self performUsingOperationQueue:operationQueue];
}
@end
以下是可以重复的NSOperation子类的示例:
MSScheduleImportOperation.h
#import <Foundation/Foundation.h>
#import "NSOperation+Repeat.h"
@interface MSScheduleImportOperation : NSOperation <NSCopying>
@property (readonly, strong, nonatomic) NSString* employeeId;
- (id)initWithEmployeeId:(NSString *)employeeId;
@end
MSScheduleImportOperation.m
#import "MSScheduleImportOperation.h"
@implementation MSScheduleImportOperation
@synthesize employeeId = __employeeId;
- (id)initWithEmployeeId:(NSString *)employeeId {
self = [super init];
__employeeId = [employeeId copy];
return self;
}
- (id)copyWithZone:(NSZone *)zone {
MSScheduleImportOperation* copy = [[MSScheduleImportOperation alloc] initWithEmployeeId:self.employeeId];
return copy;
}
- (void)main
{
...
}
@end
答案 0 :(得分:1)
操作对象是单击对象 - 也就是说,它执行一次任务,不能再用来执行它。
所以第一个问题是可能有内部因素阻止它工作。虽然,我看到你试图通过复制来解决问题。
这导致我们另一个问题是NSOperation
未宣传符合NSCopying
。
[operationQueue addOperation:[self copy]];
这一行应该抛出异常。
答案 1 :(得分:0)
而不是NSOperation
上的对象复制自身并将副本添加到NSOperationQueue
的类别 - 在更高级别管理它会更简单。例如:
+[RepeatingOperation operationBlock:(InitOperationBlock)operationBlock
queue:(NSOperationQueue*)queue
interval:(NSTimeInterval)interval];
其中InitOperationBlock
将是创建和配置操作的块。
主要的好处是API会更难搞乱。例如,在原始帖子的类别中,如果您忘记设置performUsingOperationQueue:
,repeatOperationQueue
将无声地失败。