NSOperation在执行时失败

时间:2014-07-22 15:20:42

标签: ios multithreading ios7 nsoperation

  1. 我对NSOperations有疑问。一切正常,但有时(我不知道为什么)操作块被简单地跳过。我错过了什么吗?怎么可能操作甚至不是NSLogging"操作输入"?以下是viewDidLoad的一些代码:

    //I'm using weakOperation in order to make [self.queue cancelAllOperation] method when viewWillDisappear
    
    NSBlockOperation* operation = [[NSBlockOperation alloc] init];
    __weak NSBlockOperation* weakOperation = operation;
    
    NSString *session=@"";
    @try{
        session = [self getSessionId];//getting data from CoreData
    
    }@catch(NSException *e)
    {
        NSLog(@"EXCEPTION WITH SESSION");
    }
    
    weakOperation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"operation entered");
        [self downloadJSONArray]; //doing some connection downloading and using session
        [self downloadImages]; //downloading images from urls from JSONs
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [self refresh]; //update mainThread 
        }
    }
    
    [self.queue addOperation:weakOperation];
    

    可能会有什么方法可以跳过这个区块?

  2. iOS中是否创建了最大线程数?

  3. 编辑:嘿,我已经找到了为什么会发生这种情况 - 当很多应用程序在后台运行并且iOS没有资源来排队另一个线程时它只是跳过它,如何在这种情况下表现?

1 个答案:

答案 0 :(得分:4)

您正在为弱变量分配新的NSBlockOperation。无论何时将新对象分配给弱变量,都有可能立即释放它。

如果您需要对操作的弱引用,则首先将对象分配给某个局部变量,然后获取该对象的弱引用:

NSBlockOperation* operation = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"operation entered");
    [self downloadJSONArray]; //doing some connection downloading and using session
    [self downloadImages]; //downloading images from urls from JSONs
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        [self refresh]; //update mainThread 
    }
}

__weak NSBlockOperation* weakOperation = operation;

[self.queue addOperation:weakOperation];

但是,正如方法所示,weakOperation是不必要的。您通常只需要弱引用以避免强引用周期。但目前还没有这样的循环,所以你可以这样做:

NSBlockOperation* operation = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"operation entered");
    [self downloadJSONArray]; //doing some connection downloading and using session
    [self downloadImages]; //downloading images from urls from JSONs
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        [self refresh]; //update mainThread 
    }
}

[self.queue addOperation:operation];

查看您的代码评论,您说"我使用weakOperation以便在[self.queue cancelAllOperation]"时制作viewWillDisappear方法。像这样使用weakOperation将无法实现您的目的,因为您的操作不会检查它是否被取消,因此当NSOperationQueue尝试取消它时它不会响应。

如果您想这样做,那么weakOperation模式的变体可能很有用,但您可以使用此weakOperation将其添加到队列中,而不是使用此NSBlockOperation。阻止检查操作是否被取消(并且您希望块中的弱引用以避免块保留操作本身,从而导致强引用周期)。另一个关键的观察是,不是创建一个新的NSBlockOperation* operation = [[NSBlockOperation alloc] init]; __weak NSBlockOperation* weakOperation = operation; [operation addExecutionBlock:^{ NSLog(@"operation entered"); if ([weakOperation isCancelled]) return; [self downloadJSONArray]; //doing some connection downloading and using session if ([weakOperation isCancelled]) return; [self downloadImages]; //downloading images from urls from JSONs if ([weakOperation isCancelled]) return; [[NSOperationQueue mainQueue] addOperationWithBlock:^{ [self refresh]; //update mainThread }]; }]; [self.queue addOperation:operation]; ,只需将执行块添加到您创建的原始操作中:

downloadJSONArray

显然,如果操作与downloadImagesdownloadImages相关联,则在从这些方法返回之前,它不会响应取消事件。如果您希望此操作能够合理快速地响应取消事件,您还必须使用这些方法检查取消状态。


在回答你的第二个问题时,是的,有一个最大线程数,但它是一个相当大的数字,并且还有其他因素在线程数成为问题之前发挥作用。约束因子可能是self.queue.maxConcurrentOperationCount = 4; // or 5 方法(因为您只能有5个并发下载请求)。即使这不是一个问题,您也希望限制并发操作的数量,无论如何,以减轻应用程序的峰值内存使用量。如果涉及任何网络操作,您通常需要执行以下操作:

downloadJSONArray

这样,您可以最大限度地减少使用的有限系统资源(包括线程)的数量。

顺便说一下,我假设downloadImagesNSOperation是同步方法。如果那些正在执行异步网络请求,您可能需要考虑进一步重构代码以确保操作不会过早完成(例如将其包装在并发{{1}}子类中或更改这些方法以同步运行)