通过NSURLSession / NSURLSessionDownloadTask下载完成时发送本地通知

时间:2015-07-29 20:18:46

标签: ios objective-c uilocalnotification nsurlsession nsurlsessiondownloadtask

我在NSURLSessionDownloadTask上使用NSURLSession个对象,允许用户在应用程序处于后台/设备锁定状态时下载文档。我还想告知用户个人下载已通过本地通知完成。

为此,我在-URLSession:downloadTask:didFinishDownloadingToURL:下载任务委托方法中触发本地通知,但是我想知道是否有更好的地方可以添加触发通知的代码,因为Apple解释它的方式,下载任务将被传递给系统,从中我得出的是,在应用程序背景化之后(或之后不久),下载任务的代理将不会再调用这些代理。

我的问题:添加触发本地通知的代码的最佳位置是什么?有没有人在他们的应用程序中添加这种功能有任何经验?

3 个答案:

答案 0 :(得分:8)

您可以在Apple文档URL Loading System Programming Guide中找到答案:

  

在iOS中,当后台传输完成或需要凭据时,   如果您的应用不再运行,iOS会自动重新启动您的应用   app在后台打电话给   user   应用的application:handleEventsForBackgroundURLSession:completionHandler:对象上的方法。这个电话提供   导致您的应用启动的会话的标识符。   您的应用应存储该完成处理程序,创建背景   配置对象具有相同的标识符,并创建会话   使用该配置对象。新会话是自动进行的   与正在进行的背景活动重新相关。以后,当会议   完成最后一次后台下载任务,它发送会话   委派一条UIApplicationDelegate消息。   然后,您的会话委托应该调用存储的完成处理程序。

     

如果您的应用被暂停时完成了任务,那么代表就可以了   然后是URLSessionDidFinishEventsForBackgroundURLSession:方法   使用任务和新下载文件的URL调用   与之相关。

正如您所看到的那样复杂得多,只需设置URLSession:downloadTask:didFinishDownloadingToURL:对象即可。通过委托方法,只有app处于前台模式时才会通知您。在其他情况下(应用程序处于后台模式,应用程序终止),您需要上面引用中描述的句柄delegate方法。

Apple还提供example project,其中显示了如何使用后台下载/上传任务。此示例将帮助您找到放置“本地通知”代码的位置。

答案 1 :(得分:0)

正如Visput上面解释的那样,下载完成后将调用此方法。application:handleEventsForBackgroundURLSession:completionHandler:

如果您将 NSURLSessionConfiguration 类与 backgroundSessionConfiguraton 一起使用,则会发生这种情况。你可能会错过那篇文章。

NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.BGTransfer"];
sessionConfiguration.HTTPMaximumConnectionsPerHost = 5; // To set the max concurrent connections

详细解释here

答案 2 :(得分:-1)

正如@Gautam建议的那样,你必须使用backgroundSessionConfiguration来实现你的目标。我已经附上了一个例子,希望它可以帮到你

<强> DownloadModel.h

#import "AppDelegate.h"
@interface DownloadModel : NSObject<NSURLSessionDelegate,NSURLSessionTaskDelegate,NSURLSessionDownloadDelegate>{
NSString *resp;
}

+(instancetype)shared;
-(NSURLSessionDownloadTask *) downloadTaskWithURL:(NSURL*)url ;
@end

<强> DownloadModel.m

#import "DownloadModel.h"
@interface DownloadModel ()
@property (strong,nonatomic) NSURLSession *downloadSession;
@end

@implementation DownloadModel
+(instancetype)shared{
static dispatch_once_t onceToken;
static DownloadModel *downloader=nil;

dispatch_once(&onceToken, ^{

    downloader=[DownloadModel new];
});

return downloader;

}

-(id)init{
self=[super init];
if(self){

    NSURLSessionConfiguration *downloadConfig=[NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"DownloadDemo"];
    //        downloadConfig.timeoutIntervalForRequest = 30;
    //        downloadConfig.timeoutIntervalForResource = 30;
    //        downloadConfig.HTTPMaximumConnectionsPerHost = 1;
    //        downloadConfig.sessionSendsLaunchEvents=YES;
    downloadConfig.allowsCellularAccess = YES;
    downloadConfig.networkServiceType = NSURLNetworkServiceTypeBackground;
    //        downloadConfig.discretionary = YES;
    self.downloadSession=[NSURLSession sessionWithConfiguration:downloadConfig delegate:self delegateQueue:nil];
    self.downloadSession.sessionDescription=@"Video Downloader";

}

return self;
}

-(NSURLSessionDownloadTask *) downloadTaskWithURL:(NSURL*)url{
return [self.downloadSession downloadTaskWithURL:url];
}

#pragma mark download delegate

在此方法中使用通知或本地通知

- (void)URLSession:(NSURLSession *)session downloadTask(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL(NSURL *)location{

[[NSNotificationCenter defaultCenter] postNotificationName:@"DownloadFinish" object:downloadTask userInfo:nil];
}

下载进度

- (void)URLSession:(NSURLSession *)session downloadTask(NSURLSessionDownloadTask *)downloadTask didWriteData(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{

CGFloat progress=(CGFloat)totalBytesWritten/totalBytesExpectedToWrite;

NSDictionary *userInfo=@{@"progress":@(progress)};

[[NSNotificationCenter defaultCenter] postNotificationName:@"DownloadProgress" object:downloadTask userInfo:userInfo];


}



#pragma mark delegate
-(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{
AppDelegate *appdelegate=[[UIApplication sharedApplication] delegate];

if(appdelegate.backgroundSessionCompletionHandler){
    appdelegate.backgroundSessionCompletionHandler();
    appdelegate.backgroundSessionCompletionHandler=nil;
}
}
@end

<强> AppDelegate.h

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

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

@end

<强> AppDelegate.m

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

self.backgroundSessionCompletionHandler=completionHandler;

[DownloadModel shared];
}

ViewController.m调用此方法-(NSURLSessionDownloadTask *) downloadTaskWithURL:(NSURL*)url

- (void)viewDidLoad { 

//Add Notification observers to track download progress and call the above method

[DownloadModel shared] downloadTaskWithURL:url];

} 

忘记启用后台抓取 enter image description here