我在NSURLSessionDownloadTask
上使用NSURLSession
个对象,允许用户在应用程序处于后台/设备锁定状态时下载文档。我还想告知用户个人下载已通过本地通知完成。
为此,我在-URLSession:downloadTask:didFinishDownloadingToURL:
下载任务委托方法中触发本地通知,但是我想知道是否有更好的地方可以添加触发通知的代码,因为Apple解释它的方式,下载任务将被传递给系统,从中我得出的是,在应用程序背景化之后(或之后不久),下载任务的代理将不会再调用这些代理。
我的问题:添加触发本地通知的代码的最佳位置是什么?有没有人在他们的应用程序中添加这种功能有任何经验?
答案 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];
}