亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

AF網絡和后臺傳輸

AF網絡和后臺傳輸

jeck貓 2019-11-26 10:26:56
對于如何利用新的iOS 7 NSURLSession后臺傳輸功能和AFNetworking(版本2和3),我有些困惑。我看到了WWDC 705 - What’s New in Foundation Networking會話,他們演示了后臺下載,該下載在應用終止甚至崩潰后仍然繼續。這是使用新的API application:handleEventsForBackgroundURLSession:completionHandler:以及會話的委托人最終將獲得回調并可以完成其任務的事實來完成的。因此,我想知道如何將其與AFNetworking一起使用(如果可能)以繼續在后臺下載。問題是,AFNetworking方便地使用基于塊的API來執行所有請求,但是如果應用終止或崩潰,這些塊也將消失。那么我該如何完成任務呢?也許我在這里想念什么...讓我解釋一下我的意思:例如,我的應用程序是一個照片消息傳遞應用程序,可以說我有一個PhotoMessage代表一條消息的對象,并且該對象具有諸如state -描述照片下載的狀態。resourcePath -最終下載的照片文件的路徑。因此,當我從服務器收到新消息時,我創建了一個新PhotoMessage對象,并開始下載其照片資源。PhotoMessage *newPhotoMsg = [[PhotoMessage alloc] initWithInfoFromServer:info];newPhotoMsg.state = kStateDownloading;self.photoDownloadTask = [[BGSessionManager sharedManager] downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {    NSURL *filePath = // some file url    return filePath;} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {    if (!error) {        // update the PhotoMessage Object        newPhotoMsg.state = kStateDownloadFinished;        newPhotoMsg.resourcePath = filePath;    }}];[self.photoDownloadTask resume];   如您所見,我根據完成PhotoMessage的響應使用完成塊來更新該對象。我該如何通過后臺傳輸來實現?此完成程序塊將不會被調用,因此,我無法更新newPhotoMsg。
查看完整描述

3 回答

?
慕碼人8056858

TA貢獻1803條經驗 獲得超6個贊

一些想法:


您必須確保執行“ URL加載系統編程指南”的“ 處理iOS后臺活動”部分中概述的必要編碼:


如果您NSURLSession在iOS 中使用,則下載完成后會自動重新啟動您的應用。應用程序的application:handleEventsForBackgroundURLSession:completionHandler:應用程序委托方法負責重新創建適當的會話,存儲完成處理程序,并在會話調用您的會話委托人的URLSessionDidFinishEventsForBackgroundURLSession:方法時調用該處理程序。


該指南顯示了您可以執行的一些示例。坦率地說,我覺得在WWDC 2013視頻的后半部分討論的代碼樣本中的新增基礎網絡都顯得更加清晰。


AFURLSessionManager如果僅暫停了應用程序,則的基本實現將與后臺會話配合使用(假設您已完成上述操作,則在完成網絡任務時,您會看到調用的塊)。但是,正如您猜到的那樣,“如果應用終止或崩潰” ,傳遞給AFURLSessionManager您創建NSURLSessionTask用于上載和下載的方法的特定于任務的塊參數都將丟失。


對于后臺上傳,這很煩人(因為在創建任務時指定的任務級信息進度和完成塊將不會被調用)。但是,如果您使用會話級再現(例如setTaskDidCompleteBlock和setTaskDidSendBodyDataBlock),則會被正確調用(假設在重新實例化會話管理器時始終設置這些塊)。


事實證明,丟失塊的問題實際上對于后臺下載而言更成問題,但是那里的解決方案非常相似(不要使用基于任務的塊參數,而要使用基于會話的塊,例如setDownloadTaskDidFinishDownloadingBlock)。


另一種選擇是,您可以使用默認設置(非后臺)NSURLSession,但是如果用戶在執行任務時離開應用程序,請確保您的應用程序請求一點時間來完成上傳。例如,在創建之前NSURLSessionTask,您可以創建一個UIBackgroundTaskIdentifier:


UIBackgroundTaskIdentifier __block taskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^(void) {

    // handle timeout gracefully if you can


    [[UIApplication sharedApplication] endBackgroundTask:taskId];

    taskId = UIBackgroundTaskInvalid;

}];

但是,請確保網絡任務的完成塊正確通知iOS它已完成:


if (taskId != UIBackgroundTaskInvalid) {

    [[UIApplication sharedApplication] endBackgroundTask:taskId];

    taskId = UIBackgroundTaskInvalid;

}

這沒有背景那么強大NSURLSession(例如,您有有限的可用時間),但是在某些情況下這可能很有用。


更新:


我以為我會添加一個實際的示例,說明如何使用AFNetworking進行后臺下載。


首先定義您的后臺經理。


//

//  BackgroundSessionManager.h

//

//  Created by Robert Ryan on 10/11/14.

//  Copyright (c) 2014 Robert Ryan. All rights reserved.

//


#import "AFHTTPSessionManager.h"


@interface BackgroundSessionManager : AFHTTPSessionManager


+ (instancetype)sharedManager;


@property (nonatomic, copy) void (^savedCompletionHandler)(void);


@end


//

//  BackgroundSessionManager.m

//

//  Created by Robert Ryan on 10/11/14.

//  Copyright (c) 2014 Robert Ryan. All rights reserved.

//


#import "BackgroundSessionManager.h"


static NSString * const kBackgroundSessionIdentifier = @"com.domain.backgroundsession";


@implementation BackgroundSessionManager


+ (instancetype)sharedManager {

    static id sharedMyManager = nil;

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        sharedMyManager = [[self alloc] init];

    });

    return sharedMyManager;

}


- (instancetype)init {

    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:kBackgroundSessionIdentifier];

    self = [super initWithSessionConfiguration:configuration];

    if (self) {

        [self configureDownloadFinished];            // when download done, save file

        [self configureBackgroundSessionFinished];   // when entire background session done, call completion handler

        [self configureAuthentication];              // my server uses authentication, so let's handle that; if you don't use authentication challenges, you can remove this

    }

    return self;

}


- (void)configureDownloadFinished {

    // just save the downloaded file to documents folder using filename from URL


    [self setDownloadTaskDidFinishDownloadingBlock:^NSURL *(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location) {

        if ([downloadTask.response isKindOfClass:[NSHTTPURLResponse class]]) {

            NSInteger statusCode = [(NSHTTPURLResponse *)downloadTask.response statusCode];

            if (statusCode != 200) {

                // handle error here, e.g.


                NSLog(@"%@ failed (statusCode = %ld)", [downloadTask.originalRequest.URL lastPathComponent], statusCode);

                return nil;

            }

        }


        NSString *filename      = [downloadTask.originalRequest.URL lastPathComponent];

        NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];

        NSString *path          = [documentsPath stringByAppendingPathComponent:filename];

        return [NSURL fileURLWithPath:path];

    }];


    [self setTaskDidCompleteBlock:^(NSURLSession *session, NSURLSessionTask *task, NSError *error) {

        if (error) {

            // handle error here, e.g.,


            NSLog(@"%@: %@", [task.originalRequest.URL lastPathComponent], error);

        }

    }];

}


- (void)configureBackgroundSessionFinished {

    typeof(self) __weak weakSelf = self;


    [self setDidFinishEventsForBackgroundURLSessionBlock:^(NSURLSession *session) {

        if (weakSelf.savedCompletionHandler) {

            weakSelf.savedCompletionHandler();

            weakSelf.savedCompletionHandler = nil;

        }

    }];

}


- (void)configureAuthentication {

    NSURLCredential *myCredential = [NSURLCredential credentialWithUser:@"userid" password:@"password" persistence:NSURLCredentialPersistenceForSession];


    [self setTaskDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing *credential) {

        if (challenge.previousFailureCount == 0) {

            *credential = myCredential;

            return NSURLSessionAuthChallengeUseCredential;

        } else {

            return NSURLSessionAuthChallengePerformDefaultHandling;

        }

    }];

}


@end

確保應用程序委托保存完成處理程序(根據需要實例化后臺會話):


- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler {

    NSAssert([[BackgroundSessionManager sharedManager].session.configuration.identifier isEqualToString:identifier], @"Identifiers didn't match");

    [BackgroundSessionManager sharedManager].savedCompletionHandler = completionHandler;

}

然后開始下載:


for (NSString *filename in filenames) {

    NSURL *url = [baseURL URLByAppendingPathComponent:filename];

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    [[[BackgroundSessionManager sharedManager] downloadTaskWithRequest:request progress:nil destination:nil completionHandler:nil] resume];

}

請注意,我不提供任何與任務相關的塊,因為它們與后臺會話不可靠。(即使在應用終止后,背景下載仍會繼續進行,并且這些功能塊早已消失。)人們必須依靠會話級別,并且setDownloadTaskDidFinishDownloadingBlock只能輕松地重新創建。


顯然,這是一個簡單的示例(僅一個后臺會話對象;僅使用URL的最后一個組件作為文件名將文件保存到docs文件夾中;等等),但希望它能說明這種模式。


查看完整回答
反對 回復 2019-11-26
?
寶慕林4294392

TA貢獻2021條經驗 獲得超8個贊

回調是否為塊應該沒有任何區別。實例化an時AFURLSessionManager,請確保使用實例化它NSURLSessionConfiguration backgroundSessionConfiguration:。此外,請確保調用經理setDidFinishEventsForBackgroundURLSessionBlock與你的回調塊-這就是你應該寫通常NSURLSessionDelegate的方法定義的代碼: URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session。此代碼應調用您的應用程序委托的后臺下載完成處理程序。

關于后臺下載任務的一則建議-即使在前臺運行時,它們的超時也將被忽略,這意味著您可能會在沒有響應的下載中“卡住”。這沒有記錄在任何地方,使我瘋了一段時間。第一個嫌疑人是AFNetworking,但即使直接調用NSURLSession之后,其行為也保持不變。

祝好運!


查看完整回答
反對 回復 2019-11-26
?
狐的傳說

TA貢獻1804條經驗 獲得超3個贊

AFURLSessionManager


AFURLSessionManager創建和管理的NSURLSession基于指定的對象上NSURLSessionConfiguration的對象,它符合<NSURLSessionTaskDelegate>,<NSURLSessionDataDelegate>,<NSURLSessionDownloadDelegate>,和<NSURLSessionDelegate>。


鏈接到此處的文檔


查看完整回答
反對 回復 2019-11-26
  • 3 回答
  • 0 關注
  • 907 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號