NSOperation 的对象在执行后不会从 NSOperationQueue 中删除

object of NSOperation doesn't removed from NSOperationQueue after executing

在我的 NSOperation 子类中,我设置了 4 个标志,当一个操作完成执行时,它不会被删除到 NSOperation 队列中,它是在开始时添加的,这在我的应用程序中引起了很多问题。 我想我设置这些标志的方式不正确,请你帮忙解决一下。因为我真的花了很多时间来确定这个问题。

@property(assign, nonatomic) BOOL isCancelled;
@property(nonatomic, getter=isExecuting) BOOL executing;
@property(nonatomic, getter=isFinished) BOOL finished;
@property(readonly, getter=isAsynchronous) BOOL asynchronous;

//in initialisation 
- (id)initWithURL:(NSURL*)url andRaw:(NSInteger)row
{
    if (![super init])
        return nil;
    [self setTargetURL:url];

    return self;
}
//the way I override KVO
- (BOOL)isExecuting
{
     NSLog(@"Exec");
    return (self.defaultSession != nil);//it doesn't work
}

- (BOOL)isFinished
{
    NSLog(@"Finished");
    return (self.defaultSession == nil); //it doesn't work, so I explicitly set the value
}

- (BOOL)isAsynchronous
{
    return YES;
}

- (void)cancel
{
    [super cancel];
    [self willChangeValueForKey:@"isExecuting"];
    [self willChangeValueForKey:@"isFinished"];
    self.isExecuting = NO;
    self.isFinished  = YES;
    [self didChangeValueForKey:@"isFinished"];
    [self didChangeValueForKey:@"isExecuting"];

    if(self.downloadTask.state == NSURLSessionTaskStateRunning)
        [self.downloadTask cancel];
    [self finish];
 } 
- (void)finish
{
    [self willChangeValueForKey:@"isExecuting"];
    [self willChangeValueForKey:@"isFinished"];
    self.defaultSession = nil; //NSURLSession
    self.isFinished  = YES;
    [self didChangeValueForKey:@"isFinished"];
    [self didChangeValueForKey:@"isExecuting"];
 }

提前致谢

编辑: 最后我发现了问题 - 这是队列中的 NSURLSession 。它保持对队列的强引用,不允许它从 NSOperationQueue 中释放和删除。

我做过完全相同的事情,只是在 Swift 中。

有几个方面我实现了不同,如下所列:

  • 我注意到我们不必在 异步操作。 NSOperation 取消的默认行为 方法是将 self.cancelled 布尔值设置为 true。
  • self.executing 应该只在覆盖的 start() 操作方法中设置为 true,而不是在 init 中(不确定这是否会导致任何问题)。此外,在 start() 方法中设置 self.executing = true 之前,我确保布尔值 self.cancelled 为 false。如果 self.cancelled = true,我们应该设置 self.finished = true.
  • 此外,我还为 isExecuting 和 isFinished 属性创建了一个 "didSet" 属性 观察器,我在其中调用 willChangeValueForKey 和 didChangeValueForKey。我不是 100% 确定如何在 Obj C 中复制 didSet 行为。(This 说要覆盖 setter)

请参阅关于 "Concurrency" 的 Ray Wenderlich 视频教程,其中 Sam DAvies 解释了为异步操作创建 NSoperation 子类。请注意,它仅适用于订阅者,并在 Swift 中进行了解释。我相信如果您修复第 1 点和第 2 点,您应该会看到您的问题得到解决。