【问题标题】:Keeping an NSOperation in a queue even after it completes即使在完成后也将 NSOperation 保留在队列中
【发布时间】:2012-11-30 14:42:28
【问题描述】:

通常,一旦NSOperationmain 方法完成,该操作就会被标记为完成并从队列中删除。但是,我的操作进行网络调用,我想处理重试。如何在 NSOperationQueue 中保留 NSOperation,直到我明确表示可以删除它?

【问题讨论】:

  • 如果您将 NSOperation 子类化,您可以在完成时明确告诉它。在 NSOperation 子类中保留尝试次数,只有在成功或达到预定尝试次数时才告诉它完成。
  • 您能否简单地将另一个 NSOperation 重新提交到队列以重试?
  • @Fogmeister 等一下,如果我将 NSOperation 子类化,它不会“完成”,直到我说它完成了?和main方法无关?
  • NSOperation 子类只是一个状态机。如果您不将其设置为完成(我不记得确切的属性),那么它将不会完成。我会在操作中设置一个循环,以继续尝试指定的次数。如果成功则设置完成。如果它失败了,就让循环继续。如果达到尝试次数,则放弃循环并设置完成。
  • @Fogmeister 代码完成在我输入 setX 时不会提取任何类似于 setFinished 的内容。我是否必须手动合成该属性或其他内容?

标签: ios cocoa nsoperation


【解决方案1】:

我找不到我在当前项目中所做工作的原始来源。

我将 NSOperation 子类化并执行此操作...

在.m中添加私有属性...

@property (nonatomic) BOOL executing;
@property (nonatomic) BOOL finished;
@property (nonatomic) BOOL completed;

初始化操作...

- (id)init
{
    self = [super init];
    if (self) {
        _executing = NO;
        _finished = NO;
        _completed = NO;
    }
    return self;
}

添加函数以返回属性...

- (BOOL)isExecuting { return self.executing; }
- (BOOL)isFinished { return self.finished; }
- (BOOL)isCompleted { return self.completed; }
- (BOOL)isConcurrent { return YES; }

在“开始”函数中(这是 operationQueue 调用的位...

- (void)start
{
    if ([self isCancelled]) {
        [self willChangeValueForKey:@"isFinished"];
        self.finished = YES;
        [self didChangeValueForKey:@"isFinished"];
        return;
    }

    // If the operation is not canceled, begin executing the task.
    [self willChangeValueForKey:@"isExecuting"];
    self.executing = YES;
    [self didChangeValueForKey:@"isExecuting"];

    [NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];
}

然后在 main 中放入你的工作代码...

- (void)main
{
    @try {
        //this is where your loop would go with your counter and stuff
        //when you want the operationQueue to be notified that the work
        //is done just call...
        [self completeOperation];
    }
    @catch (NSException *exception) {
        NSLog(@"Exception! %@", exception);
        [self completeOperation];
    }
}

编写完成操作的代码...

- (void)completeOperation {
    [self willChangeValueForKey:@"isFinished"];
    [self willChangeValueForKey:@"isExecuting"];

    self.executing = NO;
    self.finished = YES;

    [self didChangeValueForKey:@"isExecuting"];
    [self didChangeValueForKey:@"isFinished"];
}

就是这样。

只要你有这些,那么操作就可以工作。

您可以根据需要添加任意数量的其他函数和属性。

事实上,我实际上已经对这个类进行了子类化,因为我有一个函数可以为不同类型的对象完成所有工作(这是一个上传的东西)。我已经定义了一个函数...

- (void)uploadData
{
    //subclass this method.
}

那么我在子类中只有一个自定义的“uploadData”方法。

我发现这真的很有用,因为它可以让您精细控制何时完成操作等...

【讨论】:

  • 感谢代码示例。这真的很有帮助。两个问题:需要调用willChange/didChange值方法吗?调用 self.executing 不会自动处理吗?为什么在 main 方法中使用异常处理程序?这是您的习惯还是推荐的做法?如果是,为什么?
  • 是的,这是必要的。队列有一个属性“isExecuting”的观察者,它与我的“执行”不同。通过这样做,它会强制队列运行 - (BOOL)isExecuting。这是我第一次使用这个。我在其他地方读到过这个,它极大地改进了我的代码库。不过,从现在开始,这将是我的 MO。我瘦工具包可能是对另一个 SO 问题或其他东西的回应,找不到它。
  • 异常处理程序是我自己包含的,因为我的操作都是通过网络进行的。当我没有连接时,它会阻止整个事情失败(或应用程序崩溃)。你可能不需要它们。
  • 我找到了!这是对我自己问题的回答。 stackoverflow.com/questions/12278717/async-data-connections-ios
猜你喜欢
  • 2014-04-28
  • 1970-01-01
  • 2011-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多