В Apple iWatch фоновая задача не вызывается или не запускается с запланированным временем

Обновите местоположение, когда задача запускается, когда приложение находится в фоновом режиме. Но не удалось выполнить задачу в фоновом режиме. Мой пример кода с scheduleBackgroundRefreshWithPreferredDate выглядит следующим образом:

[WKExtension.sharedExtension scheduleBackgroundRefreshWithPreferredDate:[NSDate dateWithTimeIntervalSinceNow:60] userInfo:nil scheduledCompletion:^(NSError * _Nullable error) {

        if(error == nil) {
            NSLog(@"background refresh task re-scheduling successfuly  ");

        } else{

            NSLog(@"Error occurred while re-scheduling background refresh: %@",error.localizedDescription);
        }
    }];

После перепланирования задачи в handleBackgroundTasks:

- (void)handleBackgroundTasks:(NSSet<WKRefreshBackgroundTask *> *)backgroundTasks
{
    for (WKRefreshBackgroundTask * task in backgroundTasks) {

        if ([task isKindOfClass:[WKApplicationRefreshBackgroundTask class]]) {
            WKApplicationRefreshBackgroundTask *backgroundTask = (WKApplicationRefreshBackgroundTask*)task;
            // location update methods schedule as background task
            [self startLocationUpdate];
            [backgroundTask setTaskCompleted];

        } else if ([task isKindOfClass:[WKSnapshotRefreshBackgroundTask class]]) {
            WKSnapshotRefreshBackgroundTask *snapshotTask = (WKSnapshotRefreshBackgroundTask*)task;
            [snapshotTask setTaskCompletedWithDefaultStateRestored:YES estimatedSnapshotExpiration:[NSDate distantFuture] userInfo:nil];

        } else if ([task isKindOfClass:[WKWatchConnectivityRefreshBackgroundTask class]]) {
            WKWatchConnectivityRefreshBackgroundTask *backgroundTask = (WKWatchConnectivityRefreshBackgroundTask*)task;
            [backgroundTask setTaskCompleted];

        } else if ([task isKindOfClass:[WKURLSessionRefreshBackgroundTask class]]) {
            WKURLSessionRefreshBackgroundTask *backgroundTask = (WKURLSessionRefreshBackgroundTask*)task;
            [backgroundTask setTaskCompleted];

        } else {
            [task setTaskCompleted];
        }
    }
}

Методы фоновой задачи, как показано ниже.

-(void)startLocationUpdate {

    locationMgr = [[CLLocationManager alloc] init];
    [locationMgr setDelegate:self];

    locationMgr.desiredAccuracy = kCLLocationAccuracyBest;
    locationMgr.distanceFilter = kCLDistanceFilterNone;

    //    locationMgr.allowsBackgroundLocationUpdates = YES;

    [locationMgr requestAlwaysAuthorization];
    [locationMgr startUpdatingLocation];

    [WKExtension.sharedExtension scheduleBackgroundRefreshWithPreferredDate:[NSDate dateWithTimeIntervalSinceNow:60] userInfo:nil scheduledCompletion:^(NSError * _Nullable error) {

        if(error == nil) {
            NSLog(@"background refresh task re-scheduling successfuly  ");

        } else{

            NSLog(@"Error occurred while re-scheduling background refresh: %@",error.localizedDescription);
        }
    }];

}
- (void)locationManager:(CLLocationManager *)manager
     didUpdateLocations:(NSArray<CLLocation *> *)locations {

    NSTimeInterval locationAge = -[[locations lastObject].timestamp timeIntervalSinceNow];

    NSLog(@"Location Age : %f",locationAge);

    if (locationAge > 5.0) return;

    NSLog(@"latitude: %f longitude: %f",[locations lastObject].coordinate.latitude,[locations lastObject].coordinate.longitude);

    //NSString *strLocation = [NSString stringWithFormat:@"%f,%f" ,[locations lastObject].coordinate.latitude , [locations lastObject].coordinate.longitude];
    NSString *strLocation = @"bgLocation";

    NSDictionary *applicationData = [[NSDictionary alloc] initWithObjects:@[strLocation] forKeys:@[@"watchlocation"]];

   [[WCSession defaultSession] transferUserInfo:applicationData];

}

person Ashish    schedule 20.06.2017    source источник
comment
я хочу отправить текущее местоположение (обновленное местоположение часов) в приложение iOS, даже когда приложение часов находится в фоновом режиме   -  person Ashish    schedule 20.06.2017
comment
Нет смысла отправлять информацию о местоположении с часов на телефон с помощью WatchConnectivity. Если вы хотите использовать WatchConnectivity, приложение должно работать как минимум в фоновом режиме на телефоне, поэтому проще и оптимальнее просто получить данные о местоположении на телефоне, а не получать их на часах и отправлять на Телефон.   -  person Dávid Pásztor    schedule 20.06.2017
comment
если я получаю местоположение часов на iPhone, я вычисляю расстояние между iPhone и iWatch и запускаю базу уведомлений на расстоянии между ними   -  person Ashish    schedule 21.06.2017


Ответы (1)


Фоновое выполнение очень сложно на watchOS3. Существует много ограничений, и даже если вы успешно запланировали задачу фонового обновления, нет гарантии, что watchOS запустит ее.

Согласно моему опыту после изучения сессий и документации WWDC:

  1. watchOS3 не будет давать вашему приложению какое-либо время выполнения в фоновом режиме, если приложение не находится в Dock или не имеет активного расширения на текущем циферблате.
  2. количество задач фонового обновления ограничено примерно 1 в час для приложений в Dock и 2 в час для приложений с активным усложнением
  3. время фонового выполнения также ограничено, и если приложение превысит это время, оно будет остановлено демоном watchOS.
  4. как только вы вызываете setTaskCompleted, приложение переходит в приостановленное состояние, поэтому асинхронный метод locationManager:didUpdateLocations: из вашего кода не должен выполняться
person abjurato    schedule 20.06.2017