ios - solo - pedir huella para apagar celular
NSUserDefaults pierde sus claves y valores cuando el teléfono se reinicia pero no se desbloquea (4)
Después de un tiempo, Apple reconoció esto como un error oficial. Entonces solo nos quedan diferentes soluciones hasta que se solucione:
Si necesita los datos durante la ejecución ANTES de desbloquear el teléfono, use una de las siguientes opciones y configure la opción
NSPersistentStoreFileProtectionKey = NSFileProtectionNone
:- Guarde los datos usando Core Data. (Si necesita acceder a la base de datos en
cuando el teléfono aún no estaba desbloqueado Y NO tiene
información sensible en él, puede agregar a las opciones Array the
siguiente opción:NSPersistentStoreFileProtectionKey =
NSFileProtectionNoneNSPersistentStoreFileProtectionKey =
NSFileProtectionNoneNSPersistentStoreFileProtectionKey =
)
NSFileProtectionNone - Usa el llavero.
- Use un archivo .plist.
- Utilice archivos personalizados: (por ejemplo: .txt con un formato específico).
- De cualquier otra manera que pueda encontrar cómodo para almacenar datos.
Elige el tuyo;)
- Guarde los datos usando Core Data. (Si necesita acceder a la base de datos en
Si no necesita o no le importan los datos antes de que el teléfono se haya desbloqueado , puede usar este enfoque (Gracias @maxf):
Regístrese en la applicationProtectedDataDidBecomeAvailable:
notifique y ejecute la siguiente línea de código dentro de la devolución de llamada [NSUserDefaults resetStandardUserDefaults]
Esto hará que NSUserDefault
cargar NSUserDefault
justo después de que se le haya otorgado permiso a su teléfono para acceder a los datos protegidos, ayudándole a evitar este problema por completo.
¡Gracias por toda la ayuda!
Actualmente estamos experimentando el siguiente problema extraño con nuestra aplicación para iPhone. Como dice el título, NSUserDefaults
está perdiendo nuestras claves y valores personalizados cuando el teléfono se reinicia pero no se desbloquea, y esto sucede en un escenario muy específico.
Contexto:
Estamos utilizando
NSUserDefaults
en la aplicación para almacenar datos de usuario (por ejemplo, nombre de usuario).Nuestra aplicación tiene la ubicación habilitada en el modo de fondo.
Estamos experimentando este problema solo cuando distribuimos por aire o por Testflight. Si arrastro y coloco .ipa (el mismo que se distribuyó en el aire) en mi teléfono usando Xcode, no experimento este problema.
Situación: el usuario instala la aplicación, inicia sesión y el nombre de usuario se almacena correctamente en NSUserDefaults
. Luego, el usuario apaga el dispositivo y lo vuelve a encender y deja que el teléfono permanezca fijo por un tiempo antes de desbloquear la pantalla.
Problema: si en ese momento se activa un cambio de ubicación significativo, la aplicación entra a vivir en segundo plano pero NSUserDefaults
está vacía (solo tiene algunas teclas de Apple, pero ninguna de nuestras teclas personalizadas). Entonces, NSUserDefaults
nunca obtiene estas claves recuperadas sin importar lo que hagas (por ejemplo, si desbloqueas tu teléfono y abres la aplicación, verás que aún faltan las claves).
Cualquier ayuda o idea será realmente apreciada :)
Estaba teniendo un problema muy similar. Antecedentes de la aplicación. Use otras aplicaciones pesadas de memoria hasta que mi aplicación se descarte de la memoria. (Puede observar este evento si tiene su dispositivo conectado y xcode ejecutando la compilación. Xcode le dirá "la aplicación se terminó debido a la presión de la memoria). Desde aquí, si su aplicación está registrada para eventos de captación de fondo, se despertará en algunos apunte y vuelva a iniciar, pero en segundo plano. En este punto, si su dispositivo está bloqueado, su NSUserDefaults será nulo.
Después de depurar este caso por días, me di cuenta de que no era que NSUserDefaults estaba siendo dañado o eliminado, sino que la aplicación no tiene acceso a él debido al bloqueo del dispositivo. En realidad, puede observar este comportamiento si intenta descargar manualmente los contenidos de la aplicación a través del organizador xcode, verá que su plist que almacena la configuración NSUserDefaults no está presente si su dispositivo permanece bloqueado.
Ok, NSUserDefaults no está accesible si la aplicación se inicia en segundo plano mientras el dispositivo está bloqueado. No es gran cosa, pero la peor parte de esto es que, una vez que la aplicación se inicia en segundo plano, permanece en la memoria. En este punto SI el usuario luego desbloquea el dispositivo y lanza la aplicación al primer plano, TODAVÍA no tiene nada dentro de NSUserDefaults. Esto se debe a que una vez que la aplicación ha cargado NSUserDefaults en la memoria (que es nulo), no sabe volver a cargarlo una vez que el dispositivo se desbloquea. sincronizar no hace nada en este caso. Lo que encontré que resolvió mi problema fue llamar
[NSUserDefaults resetStandardUserDefaults]
dentro del método applicationProtectedDataDidBecomeAvailable
.
Espero que esto ayude a alguien. Esta información podría haberme ahorrado muchas horas de dolor.
Este sigue siendo el comportamiento en IOS 9.0 y lo ha sido desde IOS 7.0.
Sospecho que Apple no cambiará esto, ya que es una consecuencia del hecho de que el .plist las cargas [NSUserDefaults standardUserDefaults] está protegido con NSFileProtectionCompleteUntilFirstUserAuthentication.
Consulte también ¿Por qué no se leen NSUserDefaults después de la batería plana IOS7?
También experimentamos este problema cuando usamos un cambio de ubicación significativo en dispositivos con código de acceso habilitado. La aplicación se inicia en BG antes de que el usuario desbloquee el código de acceso, y UserDefaults no tiene nada.
Creo que es mejor terminar la aplicación antes de que ocurra la sincronización, porque las razones a continuación son:
- La sincronización de UserDefaults no se debe ejecutar una vez que UserDefaults haya sido borrado por este error.
- no podemos controlar estrictamente la llamada de sincronización porque usamos muchas bibliotecas de terceros.
- la aplicación no servirá de nada si los UserDefaults no se pueden cargar (incluso antes de que el usuario pase el bloqueo de código de acceso).
Así que aquí está nuestra solución (un poco extraña). La aplicación se destruye inmediatamente cuando se detecta la situación (estado de la aplicación = BG, UserDefaults desactivado, iOS> = 7).
No debería violar el estándar UX, ya que el usuario ni siquiera notará la finalización de la aplicación en segundo plano. (Y también ocurre antes de que el usuario pase la validación del código de acceso)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
+ (void)crashIfUserDefaultsIsInBadState
{
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")
&& [UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
if ([[NSUserDefaults standardUserDefaults] objectForKey:@"firstBootDate"]) {
NSLog(@"------- UserDefaults is healthy now.");
} else {
NSLog(@"----< WARNING >--- this app will terminate itself now, because UserDefaults is in bad state and not recoverable.");
exit(0);
}
}
[[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:@"firstBootDate"];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self.class crashIfUserDefaultsIsInBadState]; // need to put this on the FIRST LINE of didFinishLaunchingWithOptions
....
}