1

私は、NSOperation が一定の間隔でバックグラウンドで実行できるようにする Category を開発しました。これに関するフィードバック、特に私が考えていないこのアプローチの潜在的な問題について、フィードバックをいただければ幸いです。

ありがとうございました!

コードは次のとおりです。

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
4

2 に答える 2

2

Apple のドキュメントには次のように書かれています。

操作オブジェクトは単発オブジェクトです。つまり、そのタスクを 1 回実行すると、そのタスクを再度実行するために使用することはできません。

したがって、最初の問題は、動作を妨げる内部構造が存在する可能性があることです。ただし、コピーを作成することで問題を回避しようとしているようです。

NSOperationこれは、準拠するように宣伝されていないという別の問題につながりNSCopyingます。

[operationQueue addOperation:[self copy]];

この行は例外をスローする必要があります。

于 2012-05-10T15:03:02.557 に答える
1

NSOperationオブジェクトがそれ自体をコピーしてコピーを追加するカテゴリの代わりに、NSOperationQueueこれをより高いレベルで管理する方が簡単です。例えば:

+[RepeatingOperation operationBlock:(InitOperationBlock)operationBlock
                              queue:(NSOperationQueue*)queue
                           interval:(NSTimeInterval)interval];

whereInitOperationBlockは、操作が作成および構成されたブロックになります。

主な利点は、API が混乱しにくくなることです。たとえば、元の投稿のカテゴリでは、performUsingOperationQueue:設定を忘れると黙って失敗しますrepeatOperationQueue

于 2015-11-05T21:51:47.480 に答える