ios - 在 backgroundfetch IOS 中时,第一个请求的下载任务为空

标签 ios objective-c ios7 nsurlsession xcode5.0.1

我想知道您是否看到过这个,或者对为什么我在代码中看到以下行为有一些想法:我有一个带后台配置的 NSURLsession。当程序在前台运行时,我启动定期下载任务,一切正常。当我模拟 backgroundfetch(在 xcode 中)时,我的任务得到一个空值(即使请求和 session 不为空)。当然在这种情况下,我的 session 委托(delegate)永远不会被解雇来执行完成处理程序。如果我模拟后续的后台获取,它们都会在之后工作。在这一点上,如果我将应用程序带到模拟器中的前台,并模拟另一个 backgroundfetch,症状就会到处都是。我在我的 appdelegate 类中使用此代码。

非常感谢您的帮助。

- (NSURLSession *)FlickrSession
{

if(!_FlickrSession)
{
    NSLog(@"setting new FlickrSession");
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration   backgroundSessionConfiguration:FLICKR_SESSION];
    configuration.allowsCellularAccess = NO;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _FlickrSession = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
        _FlickrSession.sessionDescription = FLICKR_SESSION;
        NSLog(@" new self is  %@", _FlickrSession);
        NSLog(@"queue in session   %@", dispatch_get_current_queue());

    });
}
return _FlickrSession;

}

-(void) startFlickrFetch
{
// initialize session config and the background session

[self.FlickrSession getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks)
{
    if(![downloadTasks count])
    {
        NSLog(@"new downloadtask session %@", self.FlickrSession.sessionDescription);


        NSURLRequest *request = [NSURLRequest requestWithURL:[FlickrFetcher URLforRecentGeoreferencedPhotos]];
       // NSURLSessionDownloadTask *task = [self.FlickrSession downloadTaskWithURL:[FlickrFetcher URLforRecentGeoreferencedPhotos]];
        NSURLSessionDownloadTask *task = [self.FlickrSession downloadTaskWithRequest:request];
        task.taskDescription = FLICKR_DOWNLOAD_TASK;
        NSLog(@"new request %@", request);
        NSLog(@"new downloadtask %@", task);
        [task resume];
        //task?[task resume]:[self fireBackgroungFetchCompletionHandler];;
            //[self fireBackgroungFetchCompletionHandler];
        NSLog(@"queue in task  %@", dispatch_get_current_queue());
    }
    else
    {
        NSLog(@"resuming old downloadtask %d", [downloadTasks count]);
        for(NSURLSessionDownloadTask *task in dataTasks) [task resume];

    }

}];
NSLog(@"queue outside the block   %@", dispatch_get_current_queue());

}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    // open the file, if there is no managedContext. this is the case wjere the application  was launched directly by user
    // it did not come from the bckground state;


    //need to enable background fetch
    [[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];


//[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(documentChangedState) name:UIDocumentStateChangedNotification object: self.document];
    NSLog(@"in application didfinishlaunching");

    [self openDatabaseFile];
    [self startFlickrFetch];



    return YES;
}

-(void) application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{

    self.backgroundFetchCompletionHandler = completionHandler;
    if(self.document.documentState == UIDocumentStateNormal)
    {
       //[self openDatabaseFile];

        NSLog(@"in performFetchWithCompletionHandler");

        [self startFlickrFetch];
    }

}

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


    self.completionhandler = completionHandler;
    NSLog(@"handle event for backgroundURLsession***********");    
}

最佳答案

这可能与后台获取和后台 session 的奇怪交互有关,在这种情况下我没有任何建议。

然而,在后台,iOS 不知道等待异步调用,例如getTasksWithCompletionHandler。您可以通过使用基于 UIBackgroundTaskIdentifier† 的 [UIApplication] 开始/结束任务包装这些调用来解决此问题(在这种情况下,内部包含“结束(应用程序)任务” “获取( session )任务完成处理程序” block )。

但如果您只需要一个计数,那么我就是这样做的,我认为这更简单:

创建一个伊娃:

NSMutableSet *activeTaskIDs;

创建任务时,将其添加到集合中:

[activeTaskIDs addObject:@(task.taskIdentifier)];

任务完成后,将其删除。

你可以从那里得到你的计数,没有异步。

† 令人困惑的是,一种不同的任务。我用术语“应用程序任务”与“ session 任务”来区分。

关于ios - 在 backgroundfetch IOS 中时,第一个请求的下载任务为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20979066/

相关文章:

ios - 相邻的 "f"和 "l"字符

ios - Swift FB 应用程序邀请显示空白页面

ios - 通过 Storyboard的 Xcode 自定义控件

objective-c - iOS、objective C - 没有 XIB 和 MVC 的应用程序的好例子

objective-c - 什么需要子类化 UIView 而不是创建我们自己的 View 并将其添加到

ios - 在 iOS 7 的导航栏下添加 View 的最佳方式是什么

ios - 在 iOS 应用程序周围传递用户信息的最佳方式?

iphone - iPad 模态视图不旋转

objective-c - 从 ALAsset 获取视频时长

iOS - 无法定位异常的位置