Загрузка с использованием backgroundSessionConfiguration и NSURLSessionUploadTask вызывает сбой приложения

Я пробую новую причудливую загрузку в фоновом режиме iOS 7 с помощью NSURLSessionUploadTask, и она, кажется, работает, когда я запускаю с defaultSessionConfiguration, но как только я пытаюсь использовать backgroundSessionConfiguration, он вылетает в строке, где я вызываю uploadTaskWithRequest:

Вот пример кода ниже. Как ни странно, хотя в Интернете есть множество примеров downloadTaskWithRequest, я не могу найти ни одного, который бы сочетал фон и загрузку вместе.

//Create a session w/ background settings
NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfiguration:@"identifierString.foo"];
NSURLSession *upLoadSession = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];

//Create a file to upload
UIImage *image = [UIImage imageNamed:@"onboarding-4@2x.png"];
NSData *imageData = UIImagePNGRepresentation(image);
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *URLs = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
NSString *documentsDirectory = [[URLs objectAtIndex:0] absoluteString];
NSString *filePath = [documentsDirectory stringByAppendingString:@"testfile.png"];
[imageData writeToFile:filePath atomically:YES];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://file.upload/destination"]];
[request setHTTPMethod:@"PUT"];
NSURLSessionUploadTask *uploadTask = [upLoadSession uploadTaskWithRequest:request fromFile:[NSURL URLWithString:filePath] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    //code
}];

[uploadTask resume];

Этот код вылетает в строке с uploadTaskWithRequest:... непосредственно перед тем, как он попадает в строку возобновления в конце.

Как ни странно, это работает нормально, когда я использую любой тип конфигурации, кроме backgroundSessionConfiguration. Нужна помощь!

Заранее спасибо.

2 ответа

Решение

Ладно, это было как раз то, что я был глупым и не тщательным:

1) Я бы установил точку останова исключения, чтобы получить трассировки стека, которые мешали мне увидеть фактическую распечатку ошибки исключения - упс.

2) Невозможно использовать версию uploadTaskWithRequest, у которой есть обратный вызов завершения для backgroundSessionConfiguration (не удивительно, но все еще недостаточно хорошо документировано).

3) Запишите ваши PNG-данные в /var/... и предоставьте их для uploadTaskWithRequest с файлом:///var/... (это просто неудобно, потому что вам не нужно часто конвертировать между ними для одной последовательности команд)

Рад разместить здесь пример кода NSUrlSessionUploadTask, так как кажется, что их нет на всей сети. ЛМК, если кто-то хочет этого.

По запросу пример фоновой загрузки. Обязательно реализуйте NSURLSessionDelegate и NSURLSessionTaskDelegate по мере необходимости.

NSMutableArray *unsentPhotos = (NSMutableArray*)[sendingMessage objectForKey:@"unsentPhotos"];
TMessage *message = (TMessage*)[sendingMessage objectForKey:@"message"];
message.sendStatus = MS_PENDING_IMAGE_UPLOAD;

for (int i = 0; i < [unsentPhotos count]; i++) {
    NSString *fileName = [unsentPhotos objectAtIndex:i];
    NSLog(@"Initiating file upload for image %@", fileName);

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *srcImagePath = [NSString stringWithFormat:@"%@/messageCache/%@", [paths objectAtIndex:0], fileName];
    NSString *dataSrcImagePath = [srcImagePath stringByAppendingString:@".tmp"];

    //Encode file to data
    NSData *imageData = [NSData dataWithContentsOfFile:srcImagePath];
    if (!([imageData writeToFile:dataSrcImagePath atomically:YES])) {
        NSLog(@"Failed to save file.");
    }

    //Prepare upload request
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://blah.com"]];
    [request setHTTPMethod:@"PUT"];
    [request setValue:globalAPIToken forHTTPHeaderField:@"access_token"];
    [request setValue:[AppDelegate getMyUserID] forHTTPHeaderField:@"userid"];
    [request setValue:[NSString stringWithFormat:@"%d", message.teamID] forHTTPHeaderField:@"teamId"];
    [request setValue:[NSString stringWithFormat:@"%d", message.emailID] forHTTPHeaderField:@"messageId"];
    [request setValue:fileName forHTTPHeaderField:@"fileName"];
    [request setValue:@"1" forHTTPHeaderField:@"basefile"];

    if (i == 0) {
        //If this is the first upload in this batch, set up a new session

        //Each background session needs a unique ID, so get a random number
        NSInteger randomNumber = arc4random() % 1000000;
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfiguration: [NSString stringWithFormat:@"testSession.foo.%d", randomNumber]];
        config.HTTPMaximumConnectionsPerHost = 1;
        session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
        //Set the session ID in the sending message structure so we can retrieve it from the
        //delegate methods later
        [sendingMessage setValue:session.configuration.identifier forKey:@"sessionId"];
    }
    uploadTask = [session uploadTaskWithRequest:request fromFile:[NSURL URLWithString:[NSString stringWithFormat:@"file://%@", dataSrcImagePath]]];
    [uploadTask resume];
}
Другие вопросы по тегам