2016-08-24 2 views
4

Я занимаюсь разработкой приложения iOS, где мне нужно отслеживать, покидает ли пользователь приложение (нажимает кнопку «домой», чтобы использовать другие приложения) в то время как они «в игре», однако пользователь должен иметь возможность блокировать и блокировать свое устройство без вызова этой функции.Swift - обнаружение при отправке приложения на задний план, но не при блокировке устройства.

func applicationDidEnterBackground(application: UIApplication) { 

    if defaults.boolForKey("TimerActive"){ 
     defaults.setBool(true, forKey: "Failed") 
    } 
} 

Это, к сожалению, запускается, когда пользователь блокирует свои устройства, а также когда они выходят из приложения.

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

ответ

0

Ну, нет чистого способа сделать это. Но есть хак, который вы можете использовать. Не гарантируется, что вы продолжите работать (я тестировал до iOS 9.3, и я уверен, что он работает на бета-версии iOS 10).

Идея заключается в том, что в системе существует уведомление об заблокированном телефоне. Вы можете слушать это и в сочетании с прослушиванием фоновых/приоритетных событий в вашем приложении, вы можете определить, что происходит.

Это фрагмент кода для объекта, который будет следить за этим материалом. Создайте его из делегата приложения или где бы то ни было и сохраните сильную ссылку до тех пор, пока она вам нужна. Дайте ему делегат, он может вызывать любые события, которые вы хотите наблюдать и реагировать (или поместить код прямо там, в checkState). Я не компилировал это, поэтому, возможно, некоторые ошибки набрали его. Это происходит из кода, который я использую в приложении, но у оригинала намного больше материала, который я не буду публиковать здесь. Это в objc, но его не следует слишком сложно преобразовать в быстрый (кто-то не стесняется публиковать второй ответ быстрым или редактировать мой, но у меня нет времени, чтобы сделать это прямо сейчас)

@interface LockStateDetector : NSObject { 
    int _notify_token; 
} 

@property BOOL deviceIsLocked; 
@property BOOL appIsInBackground; 
@property NSTimer * checkStateTimer; 

@end 

@implementation LockStateDetector 

- (instancetype)init 
{ 
    self = [super init]; 
    if (self) { 
     [self registerForNotifications]; 
    } 
    return self; 
} 

- (void)dealloc 
{ 
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 
    notify_cancel(_notify_token); 
} 

- (void)registerForNotifications 
{ 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didMoveToBackground) name:UIApplicationDidEnterBackgroundNotification object:nil]; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil]; 
    __weak__ LockStateDector * wSelf = self; 
    notify_register_dispatch("com.apple.springboard.lockstate", &_notify_token, dispatch_get_main_queue(), ^(int token) { 
     __strong__ LockStateDetector sSelf = wSelf; 
     if (!sSelf) { 
      return; 
     } 
     uint64_t state = UINT64_MAX; 
     notify_get_state(token, &state); 
     sSelf.deviceIsLocked = state != 0; 
     NSLog(@"device lock state changed: %@", @(state)); 
     [sSelf checkState]; 
    }); 
} 

- (void)didBecomeActive 
{ 
    self.appIsInBackground = NO; 
    [self checkState]; 
} 

- (void)didMoveToBackground 
{ 
    self.appIsInBackground = YES; 
    [self checkState]; 
} 

- (void)checkState 
{ 
    [self.checkStateTimer invalidate]; 
    self.checkStateTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(_checkState) userInfo:nil repeats:NO]; 
} 

- (void)_checkState 
{ 
    [self.checkStateTimer invalidate]; 
    self.checkStateTimer = nil; 

    if (!self.appIsInBackground) { 
     return; 
    } 

    if (!self.deviceIsLocked) { 
     // app is in background because device was locked 
    } else { 
     // app is in background because user pressed home and switched to something else 
    } 

} 
Смежные вопросы