12

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

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

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

4

3 回答 3

9

您的问题的答案可以在 Apple 文档URL 加载系统编程指南中找到:

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

如果在您的应用程序挂起时完成了任何任务,则使用该任务以及与之关联的新下载文件的 URL 调用委托的 URLSession:downloadTask:didFinishDownloadingToURL:方法。

delegate如您所见,它比设置对象要复杂得多。通过委托方法,只有当应用程序处于前台模式时才会通知您。在其他情况下(应用程序处于后台模式,应用程序被终止)您需要处理AppDelegate上述引用中描述的方法。

Apple 还提供了示例项目,展示了如何处理后台下载/上传任务。此示例将帮助您找到放置“本地通知”代码的位置。

于 2015-08-01T22:03:12.770 回答
0

正如上面解释的 Visput,一旦下载完成,就会调用这个方法。application:handleEventsForBackgroundURLSession:completionHandler:

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

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

这里有详细解释。

于 2015-08-06T12:19:31.553 回答
-1

正如@Gautam Jain 所建议的,你必须使用它backgroundSessionConfiguration来实现你的目标。下面我附上了一个例子,希望它可以帮助你

下载模型.h

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

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

下载模型.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];

} 

不要忘记启用后台获取在此处输入图像描述

于 2015-08-06T14:14:31.050 回答