задача загрузки является нулевой для первого запроса, когда в фоновой выборке IOS

Мне интересно, видели ли вы это или у вас могут быть какие-то идеи относительно того, почему я вижу следующее поведение в своем коде: у меня есть сеанс NSURL с фоновой конфигурацией. Я инициирую периодическую задачу загрузки, когда программа работает на переднем плане, и все работает. Когда я имитирую фоновую выборку (в xcode), моя задача получает нулевое значение (даже если запрос и сеанс не являются нулевыми). конечно, в этом случае мой делегат сеанса никогда не увольняется для выполнения обработчика завершения. если я имитирую последующие фоновые выборки, все они работают потом. в этот момент, если я выведу приложение на передний план в симуляторе и смоделирую еще одну фоновую выборку, симптомы начнут проявляться повсюду. Я использую этот код в своем классе 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***********");    
}

person ehassan2014    schedule 07.01.2014    source источник
comment
Я заметил подобное поведение. В частности, если я прервусь перед созданием задачи и перешагну через нее, я получу ноль. Если я сломаюсь после создания задачи, я верну задачу. Это в симуляторе.   -  person Felix    schedule 13.01.2014
comment
Я столкнулся с той же проблемой (проверил на устройстве), те же симптомы. Когда вы запускаете downloadTaskWithRequest: в application:performFetchWithCompletionHandler:, вы получаете ноль.   -  person desudesudesu    schedule 28.01.2014
comment
Я также видел, как это происходит на реальном устройстве. (iOS 7.0.3.)   -  person TJez    schedule 07.02.2014
comment
Я также вижу, что при переходе на передний план иногда не удается вызвать didCompleteWithError или didFinishDownloadingToURL (из NSURLSessionTaskDelegate) для задач, созданных сразу после возвращения на передний план. Надеюсь, это поможет кому-то.   -  person TJez    schedule 07.02.2014


Ответы (1)


Это может иметь какое-то отношение к странному взаимодействию фоновой выборки и фонового сеанса, и в этом случае у меня нет совета.

Однако в фоновом режиме iOS не знает, что нужно ждать асинхронных вызовов, например. getTasksWithCompletionHandler. Вы можете решить эту проблему, обернув эти вызовы задачей [UIApplication] begin/end на основе UIBackgroundTaskIdentifier† (в данном случае с «задачей завершения (приложения)» внутри блока «получить обработчик завершения задач (сеанса)»).

Но если все, что вам нужно, это подсчет, вот что я сделал, что, как мне кажется, проще:

Создайте ивар:

NSMutableSet *activeTaskIDs;

При создании задачи добавьте ее в набор:

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

Когда задача завершится, удалите ее.

Вы можете получить свой счет оттуда, без асинхронности.

† Как ни странно, это другой тип задач. Я различаю термины «задачи приложения» и «задачи сеанса».

person Clay Bridges    schedule 10.02.2014