2012-05-10 3 views
0

NSOperation에 백그라운드에서 시간 간격으로 실행되는 기능을 제공하는 범주를 개발했습니다. 이 문제에 대한 의견을 듣고 싶습니다. 특히이 접근법에 대한 잠재적 인 문제는 생각지 못합니다.반복 옵션이있는 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 + 여기서 반복 할 수있는 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 

:

MSScheduleImportOperation.h

,210
#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

꽤 많은 문제점을 볼 수 있습니다. 우선, 대부분의 하위 클래스가 지원하지 않는 NSOperation 사본을 만들고 있습니다. 둘째, 취소를 처리하지 않는 것 같습니다. 작업이 취소되면이 코드는 계속해서 더 많은 인스턴스를 생성합니다. 셋째, 작업을 완료하는 데 시간이 오래 걸리면이 코드가 더 많은 인스턴스를 생성하고 동시에 여러 작업을 실행하게됩니다. –

+0

예, NSOperation의 하위 클래스는 NSCopying 프로토콜로 정의하고 (id) copyWithZone : (NSZone *) 영역을 구현해야합니다. – ScottD

+0

취소시 추가해야합니다.타이머를 반복적으로 멈추게하기 위해 nil을 할당 할 수 있어야합니다. – ScottD

답변

1

Apple documentation는 말한다 :

동작 객체가 단일 샷이 객체가 - 즉, 한번의 작업을 실행하고 실행하는 데 사용할 수 없습니다입니다 다시.

그래서 첫 번째 문제는 작동을 멈추게하는 내부 구조가있을 수 있다는 것입니다. 그러나, 나는 당신이 사본을 만들어서 문제를 해결하려고 노력하는 것을 본다.

이렇게하면 NSOperationNSCopying을 따르는 것으로 광고되지 않는다는 다른 문제가 발생합니다.

[operationQueue addOperation:[self copy]]; 

이 줄은 예외를 발생한다.

+0

네, NSOperation 클래스의 원샷 측면을 처리하려고 시도한 NSOperation 하위 클래스의 복사와 함께. 그래도 작동하는 것 같습니다. 내 하위 클래스는 NSCopying 프로토콜로 정의되며 copyWithZone : (NSZone *) 영역을 구현합니다. NSOperation의 어떤 속성이 deep-copied가되지 않을지 걱정 될 것입니다. 옳은? – ScottD

0

NSOperation의 범주 대신 개체가 자체를 복사하고 NSOperationQueue에 사본을 추가합니다. 더 높은 수준에서이를 관리하는 것이 더 간단합니다. 예를 들어 InitOperationBlock 조작 만들고 구성된 블록 것이다

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

.

주요 장점은 API가 엉망이되기 어렵다는 것입니다. 원래 게시물의 카테고리에서 예를 들어 repeatOperationQueue을 잊어 버리면 performUsingOperationQueue:이 자동으로 실패합니다.