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

时间:2016-04-02 23:55:56

标签: ios key-value-observing nsoperationqueue

在我的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中取消分配和删除它。

1 个答案:

答案 0 :(得分:2)

我完成了同样的事情,在Swift中的albiet。

我有不同的实施方式,下面列出了几个方面:

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

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