0

I've a uitableview which shows images in each cell, which are downloaded online.

To make this call async, I use NSBlockoperation. I prefer to use this, because i used GCD before but you cannot cancel GCD. The reason is that if I leave the view, the images gets downloaded at the background of the App, and when I get into the previous view again GCD would let it queue all again, so eventually there would be a whole stack of images and the user would never see the uitableview. So thats why I choose for NSBlockoperation.

However, my blocks don't get cancelled. This is the code I use (it is a part of - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { ):

// Create an operation without any work to do
    downloadImageOperation = [NSBlockOperation new];

    // Make a weak reference to the operation. This is used to check if the operation
    // has been cancelled from within the block
    __weak NSBlockOperation* operation = downloadImageOperation;


    // Give the operation some work to do
    [downloadImageOperation addExecutionBlock: ^() {
        // Download the image
        NSData *data = [NSData dataWithContentsOfURL:[newsimages objectAtIndex:indexPath.row]];;
        UIImage *image = [[UIImage alloc] initWithData:data];
         NSLog(@"%@",image);
        // Make sure the operation was not cancelled whilst the download was in progress
        if (operation.isCancelled) {
            return;
            NSLog(@"gestopt");
        }
        if (image != nil) {

            NSData* imageData = UIImagePNGRepresentation(image);

            [fileManager createFileAtPath:path contents:imageData attributes:nil];
            cell.imageView.image = image;
            cell.imageView.layer.masksToBounds = YES;
            cell.imageView.layer.cornerRadius = 15.0;

        }

        // Do something with the image
    }];

    // Schedule the download by adding the download operation to the queue
    [queuee addOperation:downloadImageOperation];

I've used this code to cancel:

-(void)viewDidDisappear:(BOOL)animated {
[downloadImageOperation cancel];
}

However, my NSLog tells me that even after my view dissappeared (i put an nslog there), there are still blocks.

 2012-09-12 21:32:31.869 App[1631:1a07] <UIImage: 0x3965b0>
 2012-09-12 21:32:32.508 App[1631:1907] <UIImage: 0x180d40>
 2012-09-12 21:32:32.620 App[1631:707] view dissappear!
 2012-09-12 21:32:33.089 App[1631:3a03] <UIImage: 0x3a4380>
 2012-09-12 21:32:33.329 App[1631:5a03] <UIImage: 0x198720>

Notice: there are each time 4 cells displayed in the view, so I think that even though I leave the view they are still in the queue..

4

1 回答 1

1

您的代码似乎从来没有超过一个块排队 - 这是正确的吗?如果不是,那么您需要将“取消”发送到队列而不是操作。

无论如何,您的问题很可能是这一行:

NSData *data = [NSData dataWithContentsOfURL:[newsimages objectAtIndex:indexPath.row]];;

该下载正在为您同步完成 - 因此,如果您在此消息之后发送“取消”,那么很长一段时间都不会看到取消。这就是为什么大多数开发人员使用并发 NSOperations 使用异步 NSURLConnections 来进行下载 - 所以实时获取取消消息。

假设这是 ARC,您可以在 dealloc 中添加日志,以验证操作实际上已完成或已取消,并且已正确释放。[请注意,您上面的日志是在返回之后,因此永远不会被调用。您还应该在周围散布更多 isCancelled 消息,以便在取消后尽快停止。]

于 2012-09-12T20:08:28.403 回答