1

я мое приложение у меня есть вид таблицы с пользовательской ячейкой, то есть:метод вызова NSURLSession внутри подкласса NSOperation

@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]; 
    } 

изображение вообще не загружается, очередь просто входит в метод настройки, и все это. Пожалуйста, сообщите мне, что случилось? Спасибо заранее.

EDIT: Обновление интерфейса:

-(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]; 
    }); 
} 
+0

Кстати, в вашем методе 'cancel' вы, вероятно, захотите вызвать' [super cancel] ', чтобы вам понравилось стандартное поведение' NSOperation'. Кроме того, в 'main', обязательно выполняйте' isFinished' KVO. Наконец, я полагаю, вы определили свой класс NSOperation как асинхронный? – Rob

+0

@Rob, я только что создал подкласс, я никогда не упоминал, что он должен быть асинхронным, где я должен это делать? – Melany

+0

Да, это должно быть асинхронно, потому что 'NSURLSession' является асинхронным. Поэтому (а) 'isAsynchronous' должен возвращать' true'; (b) вам нужно выполнить 'isExecuting' и' isFinished' KVO и иметь аналогично названные методы, которые возвращают правильные значения. Если вы ищете «асинхронный подкласс NSOperation», вы, скорее всего, найдете множество хитов по всему этому. Но вам определенно необходимо выполнить эту асинхронную операцию, иначе ваша операция завершится и будет освобождена до вызова любого из методов делегата. – Rob

ответ

1

Ваш класс является подклассом NSOperation, не NSOperationQueue Таким образом, вы можете не указывать его использовать self в качестве целевой очереди для NSURLSession объекта. Честно говоря, вы просто используете nil для параметра очереди операции, так как вам все равно, в какой очереди запущены методы делегата. Или вы можете создать свою собственную очередь операций, если хотите. Но вы не можете использовать self.

Но не забудьте отправить обновления UI обратно в основную очередь.

Кроме того, вы должны сделать это асинхронным подклассом NSOperation, иначе операция завершится и будет освобождена до того, как ваши методы делегата получат возможность вызова.

Как небольшое наблюдение, я предлагаю переименовать этот класс в MyOperation, чтобы избежать путаницы между операциями и очередями операций.

+0

спасибо, Итак, я должен внутри основного метода создать экземпляр очереди NSOperation и добавить его вместо self? – Melany

+0

Во всех учебниках я увидел, что существует необходимость создать подкласс NSOperation, а не OperationQueue – Melany

+0

Подкласс «NSOperation» является правильным. Но для параметра 'queue'' NSURLSession' я бы просто использовал 'nil', поскольку вам, вероятно, не важно, какая из них использует NSURLSession. (Не путайте очередь для своих операций с очередью, которую использует NSURLSession.) Просто убедитесь, что отправили обновления пользовательского интерфейса обратно в основную очередь. – Rob