【问题标题】:Call NSURLSession method from inside the subclass of NSOperation从 NSOperation 的子类内部调用 NSURLSession 方法
【发布时间】:2016-03-30 23:09:42
【问题描述】:

我的应用程序有自定义单元格的表格视图,其中有:

@property (weak, nonatomic) IBOutlet UIImageView *image;
@property (weak, nonatomic) IBOutlet UILabel *nameOfImage;
@property (weak, nonatomic) IBOutlet UIButton *start;

我需要异步下载任意数量的图像(通过按很多开始按钮)。为此,我创建了 NSOperation 的子类 - MyOperationQueue。它的实现如下所示:

- (id)initWithURL:(NSURL*)url andRaw:(NSInteger)row
{
    if (![super init])
        return nil;
    [self setTargetURL:url];
    [self setCurrentCell:row];
    self.customCell = [[CustomTableViewCell alloc]init];
    self.tableView = [ContentTableView sharedManager];
    return self;
}

- (void)main
{
    if ([self isCancelled])return;
    self.defaultSession = [self configureSession];
    NSURLSessionDownloadTask *task = [self.defaultSession downloadTaskWithURL:self.targetURL];
    if ([self isCancelled])  return;
    [task resume];
 }

- (void)cancel
{
    self.isCancelled = YES;
       if(self.downloadTask.state == NSURLSessionTaskStateRunning)
        [self.downloadTask cancel];
}

在这些方法中,我还在这里描述了 NSURLSession 方法:

    - (NSURLSession *) configureSession //it visits it
    {
 NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self.tableView **delegateQueue:self**];  //self - warning - incompatible pointer type sending "MyOperationQueue" to "NSOperationQueue" _Nullable.

}

-(void)URLSession:(NSURLSession *)session
         downloadTask:(NSURLSessionDownloadTask *)downloadTask
         didWriteData:(int64_t)bytesWritten
    totalBytesWritten:(int64_t)totalBytesWritten
    totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite // don't visit

-(void)URLSession:(NSURLSession *)session
     downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location    // don't visit

我在 TableView 的方法中创建了自定义队列:

   - (void)didClickStartAtIndex:(NSInteger)cellIndex withData:(CustomTableViewCell*)data
    {
        NSURL *url = [NSURL URLWithString: tmp.imeageURL];
        MyOperationQueue * one = [[MyOperationQueue alloc]initWithURL:url andRaw:self.selectedCell];
        [self.queue addOperation:one];
    }

图像根本没有加载,队列只是进入配置方法,仅此而已。请告诉我怎么了? 提前谢谢你。

编辑: 更新界面:

-(void)URLSession:(NSURLSession *)session
     downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
    NSLog(@"didFinishDownloadingToURL - Queue");
    NSData *d = [NSData dataWithContentsOfURL:location];
    UIImage *im = [UIImage imageWithData:d];
    dispatch_async(dispatch_get_main_queue(), ^{
        self.customCell.image.image = im;
        self.customCell.realProgressStatus.text = @"Downloaded";
        [self.tableView.tableView reloadData];
    });
}

【问题讨论】:

  • 顺便说一句,在您的 cancel 方法中,您可能希望调用 [super cancel] 以便您享受标准的 NSOperation 行为。此外,在main 中,确保执行isFinished KVO。最后,我假设您将 NSOperation 类定义为异步的?
  • @Rob,我刚刚创建了它的子类,我从来没有提到它应该是异步的,我应该在哪里做呢?
  • 是的,它必须是异步的,因为NSURLSession 是异步的。所以(a)isAsynchronous必须返回true; (b) 你必须做isExecutingisFinished KVO 并且有类似命名的方法来返回正确的值。如果您搜索“异步NSOperation 子类”,您可能会在所有这些内容上找到很多匹配项。但是您肯定需要进行此异步操作,否则您的操作将在调用任何委托方法之前终止并被释放。
  • @Rob 非常感谢你,我终于开始明白哪里出了问题,我根据你的建议改正了。

标签: ios objective-c nsurlsession nsoperation nsoperationqueue


【解决方案1】:

您的类是NSOperation 的子类,而不是NSOperationQueue 所以您不能指定它使用self 作为NSURLSession 对象的目标队列。坦率地说,您只需将nil 用于操作队列参数,因为您不关心委托方法在哪个队列上运行。或者,如果需要,您可以创建自己的操作队列。但是你不能使用self

但请确保将所有 UI 更新分派回主队列。

此外,您必须将其设为异步 NSOperation 子类,否则操作将在您的委托方法有机会被调用之前终止并被释放。

作为一个小观察,我建议将这个类重命名为MyOperation,以避免操作和操作队列之间的混淆。

【讨论】:

  • 谢谢,所以我应该在 main 方法中创建一个 NSOperation 队列的实例并添加它而不是 self?
  • 在所有教程中,我看到需要创建 NSOperation 的子类,而不是 OperationQueue
  • 子类化NSOperation 是正确的。但是对于NSURLSessionqueue 参数,我只使用nil,因为您可能不在乎NSURLSession 使用哪个队列。 (不要将您的操作队列与 NSURLSession 使用的队列混淆。)只需确保将 UI 更新分派回主队列即可。
  • 谢谢,我更新了一个问题,在底部我只是反映了 NSURLSession 的 1 个方法,它位于 MyOperation - 我可以用这种方式更新 UI 吗?
  • 顺便说一句,即使我将委托设置为新的,它仍然不会访问配置旁边的方法。可能是什么原因?当它在主队列上完成时,一切正常。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多