¿Hay alguna manera de verificar si el dispositivo iOS está bloqueado / desbloqueado?

He usado actualizaciones de ubicación GPS en mi aplicación. Quiero detectar si el dispositivo iOS está en modo de suspensión para poder desactivar las actualizaciones de ubicación GPS y optimizar el uso de la batería. Ya he probado pausesLocationupdates en iOS 6, pero no funciona como se desea. Quiero desactivar las actualizaciones de ubicación GPS tan pronto como el dispositivo entre en modo de suspensión. Quiero detectar el evento de locking / deslocking en el dispositivo.

¿Hay alguna forma de lograr esta funcionalidad?

hasta ahora recibí las notificaciones darwin como se indica a continuación

-(void)registerForall { //Screen lock notifications CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center NULL, // observer displayStatusChanged, // callback CFSTR("com.apple.iokit.hid.displayStatus"), // event name NULL, // object CFNotificationSuspensionBehaviorDeliverImmediately); CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center NULL, // observer displayStatusChanged, // callback CFSTR("com.apple.springboard.lockstate"), // event name NULL, // object CFNotificationSuspensionBehaviorDeliverImmediately); CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center NULL, // observer displayStatusChanged, // callback CFSTR("com.apple.springboard.hasBlankedScreen"), // event name NULL, // object CFNotificationSuspensionBehaviorDeliverImmediately); CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center NULL, // observer displayStatusChanged, // callback CFSTR("com.apple.springboard.lockcomplete"), // event name NULL, // object CFNotificationSuspensionBehaviorDeliverImmediately); } //call back static void displayStatusChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { NSLog(@"IN Display status changed"); NSLog(@"Darwin notification NAME = %@",name); } 

Puedo obtener las notificaciones de Darwin cuando el dispositivo está bloqueado / desbloqueado, pero el verdadero problema es cómo identificar si la notificación proviene del locking o del deslocking del dispositivo. Los registros de la consola son:

  LockDetectDemo[2086] : IN Display status changed LockDetectDemo[2086] : Darwin notification NAME = com.apple.springboard.lockcomplete LockDetectDemo[2086] : IN Display status changed LockDetectDemo[2086] : Darwin notification NAME = com.apple.springboard.lockstate LockDetectDemo[2086] : IN Display status changed LockDetectDemo[2086] : Darwin notification NAME = com.apple.springboard.hasBlankedScreen LockDetectDemo[2086] : IN Display status changed LockDetectDemo[2086] : Darwin notification NAME = com.apple.iokit.hid.displayStatus 

Cualquier API privada también sería suficiente. Gracias por adelantado.

Lo solucioné así:

 //call back static void displayStatusChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { // the "com.apple.springboard.lockcomplete" notification will always come after the "com.apple.springboard.lockstate" notification CFStringRef nameCFString = (CFStringRef)name; NSString *lockState = (NSString*)nameCFString; NSLog(@"Darwin notification NAME = %@",name); if([lockState isEqualToString:@"com.apple.springboard.lockcomplete"]) { NSLog(@"DEVICE LOCKED"); //Logic to disable the GPS } else { NSLog(@"LOCK STATUS CHANGED"); //Logic to enable the GPS } } -(void)registerforDeviceLockNotif { //Screen lock notifications CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center NULL, // observer displayStatusChanged, // callback CFSTR("com.apple.springboard.lockcomplete"), // event name NULL, // object CFNotificationSuspensionBehaviorDeliverImmediately); CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center NULL, // observer displayStatusChanged, // callback CFSTR("com.apple.springboard.lockstate"), // event name NULL, // object CFNotificationSuspensionBehaviorDeliverImmediately); } 

Nota: la notificación ” com.apple.springboard.lockcomplete ” siempre vendrá después de la notificación “com.apple.springboard.lockstate”

Actualizar

El orden de las dos notificaciones ya no se puede confiar, a partir de versiones recientes de iOS

Las aplicaciones no pueden escuchar las notificaciones de locking del dispositivo ahora.

Yo había recibido esto:

Estimado desarrollador,

Hemos descubierto uno o más problemas con su presentación reciente de “xxxx”. Para procesar su envío, los siguientes problemas deben ser corregidos:

Operación no compatible: las aplicaciones no pueden escuchar las notificaciones de locking del dispositivo.

Una vez que se hayan corregido estos problemas, use Xcode o Application Loader para cargar un nuevo binario en iTunes Connect. Elija el nuevo binario en la página Detalles de la aplicación en Mis aplicaciones en iTunes Connect y haga clic en Enviar para revisión.

Saludos,

El equipo de App Store
26 de abril de 2017 a las 10:56

/ * Aplicación de registro para detectar el estado de locking * /

  -(void)registerAppforDetectLockState { int notify_token; notify_register_dispatch("com.apple.springboard.lockstate", &notify_token,dispatch_get_main_queue(), ^(int token) { uint64_t state = UINT64_MAX; notify_get_state(token, &state); if(state == 0) { NSLog(@"unlock device"); } else { NSLog(@"lock device"); } NSLog(@"com.apple.springboard.lockstate = %llu", state); UILocalNotification *notification = [[UILocalNotification alloc]init]; notification.repeatInterval = NSDayCalendarUnit; [notification setAlertBody:@"Hello world!! I come becoz you lock/unlock your device :)"]; notification.alertAction = @"View"; notification.alertAction = @"Yes"; [notification setFireDate:[NSDate dateWithTimeIntervalSinceNow:1]]; notification.soundName = UILocalNotificationDefaultSoundName; [notification setTimeZone:[NSTimeZone defaultTimeZone]]; [[UIApplication sharedApplication] presentLocalNotificationNow:notification]; }); } 

Aquí hay una mejor solución

 #import  #define kNotificationNameDidChangeDisplayStatus @"com.apple.iokit.hid.displayStatus" @interface YourClass () { int _notifyTokenForDidChangeDisplayStatus; } @property (nonatomic, assign, getter = isDisplayOn) BOOL displayOn; @property (nonatomic, assign, getter = isRegisteredForDarwinNotifications) BOOL registeredForDarwinNotifications; @end - (void)registerForSomeNotifications { // // Display notifications // __weak YourClass *weakSelf = self; uint32_t result = notify_register_dispatch(kNotificationNameDidChangeDisplayStatus.UTF8String, &_notifyTokenForDidChangeDisplayStatus, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0l), ^(int info) { __strong YourClass *strongSelf = weakSelf; if (strongSelf) { uint64_t state; notify_get_state(_notifyTokenForDidChangeDisplayStatus, &state); strongSelf.displayOn = (BOOL)state; } }); if (result != NOTIFY_STATUS_OK) { self.registeredForDarwinNotifications = NO; return; } self.registeredForDarwinNotifications = YES; } - (void)unregisterFromSomeNotifications { // // Display notifications // uint32_t result = notify_cancel(_notifyTokenForDidChangeDisplayStatus); if (result == NOTIFY_STATUS_OK) { self.registeredForDarwinNotifications = NO; } } 

Para su caso de uso particular, verificar el brillo de la pantalla puede ser útil.

 var isScreenLocked: Bool { return UIScreen.main.brightness == 0.0 } 

Jimmy proporcionó una gran solución, pero es más seguro pasar (__bridge const void *)(self) como observador.

 CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge const void *)(self), displayStatusChanged, CFSTR("com.apple.springboard.lockcomplete"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); 

Esto le permite eliminar adecuadamente al observador.