2016-08-24 22 views
4

ユーザーがアプリを離れるかどうかを追跡する必要があるiOSアプリを開発中です(他のアプリを使用するにはホームボタンを押します)しかし、それらは「ゲーム中」であるが、ユーザは、この機能が呼び出されない限り、デバイスをロックおよびアンロックすることができるはずである。スウィフト - アプリがバックグラウンドに送信されたときに検出されますが、デバイスがロックされているときに検出されない

func applicationDidEnterBackground(application: UIApplication) { 

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

残念なことに、ユーザーが端末をロックしてアプリを終了すると、これが発生します。

アプリに関する小さなコンテキスト:アプリは、自分の仕事に集中し、あらかじめ設定された期間、自分の携帯電話に注意を払うことを奨励します。 タイマーがアクティブな間にユーザーが終了時にアプリを再開するように促す方法の他の提案は、デバイスをロックするときには大いに歓迎されるでしょう!

答えて

0

まあ、これを行うためのきれいな方法はありません。しかし、あなたが使うことができるハックがあります。しかし、私はiOS 9.3までテストしており、iOS 10ベータ版で動作することは確かです。

考えられるのは、ロックされている電話機に関するシステム全体の通知があるということです。あなたはそれを聞くことができ、あなたのアプリでバックグラウンド/フォアグラウンドのイベントを聞くことと相まって、何が起きているのかを判断することができます。

これは、このものを監視するオブジェクトのコードです。あなたがそれを必要とする限り、アプリケーションの代理人またはどこからでもそれを作成し、強力な参照を保持します。参加者にオブザーバーを与えて、観察して反応させたいイベントを呼び出すことができます(またはcheckStateにコードを置くことができます)。私はこれをコンパイルしていないので、タイプミスをした可能性があります。それは私がアプリで使っているコードから派生したものですが、オリジナルには私がここに投稿しないもっとたくさんのものがあります。それはobjcですが、速やかに変換するのは難しくありません(誰かが速やかに2番目の回答を投稿するか、私の編集を自由にしますが、今はそれを行う時間がありません)。

@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 
    } 

} 
関連する問題