1

首先:我对 RestKit 很陌生,所以也许这是一个很容易解决的问题。

我正在尝试下载很多文件。目前我使用getObjectsAtPath:parameters:success:failure:方法RKObjectManager来获取我的对象并将其映射到restkit。

但是,似乎它过早地开始了一些下载,然后当它们在队列中时超时。

我正在使用的代码:

- (void)removeResponseAndRequestDescriptors
{
    RKObjectManager *objectManager = [RKObjectManager sharedManager];
    [objectManager.requestDescriptors enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        [objectManager removeRequestDescriptor:obj];
    }];

    [objectManager.responseDescriptors enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        [objectManager removeResponseDescriptor:obj];
    }];
}

.

- (void)downloadAudioFileForAudio:(IBAudio *)audio
                           inBook:(IBBook *)book
                  downloadStatus:(void (^)(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead))downloadStatus
                         success:(void (^)(void))success
                         failure:(void (^)(NSError *error))failure
{
    RKObjectManager *objectManager = [RKObjectManager sharedManager];

    NSString *sessionID = (book.parent ? book.parent.user.session.sessionID : book.user.session.sessionID);
    [objectManager.HTTPClient setDefaultHeader:@"Accept" value:@"application/octet-stream"];
    [objectManager.HTTPClient setDefaultHeader:@"Session-Id" value:sessionID];

    [objectManager.HTTPClient getPath:[IBProperties downloadAudioEndPointWithIsbn:book.isbn andAnchor:audio.anchor] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {

        NSString *folderPath = [self folderPathForBook:book];
        NSString *audioPath = [folderPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mp3", audio.anchor]];
        NSData *audioData = [NSData dataWithData:responseObject];

        NSError *fileSystemSaveError;
        [self saveFile:audioData toFilePath:audioPath error:&fileSystemSaveError];
        if (fileSystemSaveError) {
            failure(fileSystemSaveError);
            return;
        }

        // Saving the context asap in case the app dies before it can autosave.
        NSError *coreDataSaveerror;
        [[[[RKObjectManager sharedManager] managedObjectStore] mainQueueManagedObjectContext] save:&coreDataSaveerror];
        if (coreDataSaveerror) {
            failure(coreDataSaveerror);
            return;
        }

        [audio setFilePath:audioPath];
        success();
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        failure(error);
    }];

    [objectManager.HTTPClient.operationQueue.operations.lastObject setDownloadProgressBlock:downloadStatus];
}

.

- (void)downloadAudioFiles
{
    for (IBAudio *audio in self.book.bookData.audios) {
        self.numberOfDownloads++;
        [self.downloadPercentagesFiles addObject:[[IBDownloadStatusOfAFile alloc] init]];
        NSInteger arrayIndex = [self.downloadPercentagesFiles count] - 1;

        [[IBDataBackendFetcher sharedBackendFetcher] downloadAudioFileForAudio:audio inBook:self.book downloadStatus:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
            IBDownloadStatusOfAFile *statusOfFile = [self.downloadPercentagesFiles objectAtIndex:arrayIndex];
            statusOfFile.bytesRead = bytesRead;
            statusOfFile.totalBytesRead = totalBytesRead;
            statusOfFile.totalBytesExpectedToRead = totalBytesExpectedToRead;
            [self updateDownloadProgress];
        } success:^{
            [self downloadDidComplete];
        } failure:^(NSError *error) {
            [self.dataProviderDelegate downloadDidFailWithError:error forBookDownloader:self];
        }];
    }
}

似乎它一次开始所有下载,但实际下载并未开始。所以最后一次下载会超时。

有没有更好的方法来解决这个问题?

4

2 回答 2

1

将队列上的最大并发操作数设置为某个合理的值,例如 5。

[objectManager.HTTPClient.operationQueue setMaxConcurrentOperationCount:5];

(在您开始任何请求之前)

于 2013-08-22T17:29:39.017 回答
1

所有下载都将同时运行,因为您正在getPath:连续进行所有调用(它们是异步调用)。由于每次下载都需要一段时间才能完成,这会导致后续调用超时。

如果您希望每次下载仅在前一个下载完成后发生,我会创建一个名为的方法getNextAudioFile:和一个迭代器类属性。然后,在success和的failure块中getPath:,递增您的迭代器并调用getNextAudioFile:

示例代码:

- (void)downloadAudioFiles
{
   // No for loop
   self.iterator = 0;

   // your call to DownloadAudioFileForAudio: ... for the first audio goes here
}

- (void)downloadAudioFileForAudio:(IBAudio *)audio
                           inBook:(IBBook *)book
                  downloadStatus:(void (^)(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead))downloadStatus
                         success:(void (^)(void))success
                         failure:(void (^)(NSError *error))failure
{
  // your code ...

  [objectManager.HTTPClient getPath:[IBProperties downloadAudioEndPointWithIsbn:book.isbn andAnchor:audio.anchor] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject){

    // your code...

    // increment and get the next file
    self.iterator++;
    [self getNextAudioFile];

  } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    failure(error);

    // increment and get the next file
    self.iterator++;
    [self getNextAudioFile];
  }];
}

- (void)getNextAudioFile
{
  if(self.iterator < [self.book.bookData.audios count]){
    // make your downloadAudioFileForAudio: call for the next audio
  }
}

至少是这样的想法!希望它有所帮助。

于 2013-08-22T17:49:18.363 回答