Задача загрузки равна нулю для первого запроса, когда в backgroundfetch IOS
Мне было интересно, видели ли вы это или у вас могут быть некоторые идеи относительно того, почему я вижу следующее поведение в моем коде: у меня есть NSURLsession с фоновой конфигурацией. Я запускаю периодическую задачу загрузки, когда программа работает на переднем плане, и все работает. Когда я имитирую backgroundfetch (в xcode), моя задача получает нулевое значение (даже если запрос и сеанс не равны null). Конечно, в этом случае мой делегат сеанса никогда не будет запущен для выполнения обработчика завершения. если я имитирую последующие фоновые выборки, они все работают потом. в этот момент, если я вывожу приложение на передний план в симуляторе и симулирую еще одну фоновую выборку, симптомы исчезнут со всех сторон. Я использую этот код в своем классе 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***********");
}
1 ответ
Это может быть связано со странным взаимодействием фоновой выборки и фоновой сессии, и в этом случае у меня нет никаких советов.
Однако в фоновом режиме iOS не знает, как ждать асинхронных вызовов, например getTasksWithCompletionHandler
, Вы можете решить эту проблему, заключив эти вызовы в UIBackgroundTaskIdentifier
†-основан [UIApplication]
задача начала / конца (в данном случае с "задачей конца (приложения)" внутри блока "обработчик завершения задач получения (сессии)").
Но если все, что вам нужно, это подсчет, вот что я сделал, что я думаю, проще:
Создайте ивар:
NSMutableSet *activeTaskIDs;
Когда вы создаете задачу, добавьте ее в набор:
[activeTaskIDs addObject:@(task.taskIdentifier)];
Когда задача завершится, удалите ее.
Вы можете получить отсчет отсюда, без асинхронности.
† Путаница, другой вид задачи. Я различаю термины "задачи приложения" и "задачи сессии".