Borrar NSUserDefaults

Respuestas:

514

Puede eliminar el dominio persistente de la aplicación de esta manera:

NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];

En Swift 3 y posterior:

if let bundleID = Bundle.main.bundleIdentifier {
    UserDefaults.standard.removePersistentDomain(forName: bundleID)
}

Esto es similar a la respuesta de @samvermette pero es un poco más limpio en mi opinión.

Christopher Rogers
fuente
Esto funcionó muy bien, gracias! Simplemente no olvides lanzar appDomain después.
IcyBlueRose
15
@IcyBlueRose: bundleIdentifier es un objeto lanzado automáticamente, ya que no comienza con init o new, por lo que lo liberaría en exceso.
Christopher Rogers
1
¡Es bueno saberlo, gracias! Pero estaba hablando de la cadena appDomain. ¿Ese auto también se lanzó?
IcyBlueRose
2
@IcyBlueRose El objeto devuelto por bundleIdentifier es el mismo que el objeto al que hace referencia appDomain.
Christopher Rogers
2
Parece que ya no puedo hacer que esto funcione en 10.8, ¿alguien podría confirmar que esto funciona? Aquí hay una pregunta SO relacionada: stackoverflow.com/questions/13595415/…
DaGaMs
102

Este código restablece los valores predeterminados al dominio de registro:

[[NSUserDefaults standardUserDefaults] setPersistentDomain:[NSDictionary dictionary] forName:[[NSBundle mainBundle] bundleIdentifier]];

En otras palabras, es removeObjectForKeypara cada clave que haya registrado en esa aplicación.

Créditos a Ken Thomases en este hilo de los foros de desarrolladores de Apple .

samvermette
fuente
44
Gracias un montón. Por qué [NSUserDefaults resetStandardUserDefaults]no hace esto está más allá de mí.
jakeboxer
2
@jboxer Acabo de pasar un tiempo estudiando la documentación de Apple y resetStandardUserDefaults básicamente vacía el búfer en memoria en el disco y lo limpia. Entonces, la próxima vez que intente recuperar un valor, debe tomarlo del disco. NSManagedObjectContext de Core Data también utiliza una terminología similar de "restablecimiento".
Christopher Rogers
2
Vaya, quise decir que borra el búfer en memoria sin escribirlo en el disco. Por lo tanto, cualquier cambio que haya realizado antes de sincronizar con el disco se perderá.
Christopher Rogers
44
Christopher, creo que lo tienes al revés, aunque tal vez las cosas cambiaron. resetStandardUserDefaults es la llamada con el nombre más confuso que he visto hasta ahora en iOS. Los documentos de Apple dicen "Sincroniza cualquier cambio realizado en el objeto predeterminado del usuario compartido y lo libera de la memoria". por lo que realmente debería llamarse flushAndReleaseStandardUserDefaults. Me estoy tomando el tiempo para comentar un comentario anterior porque esta llamada me atrapó y quiero evitar que alguien más se queme (ahora tengo que decirle a un cliente que necesito actualizar 90 aplicaciones).
Andy Dent
97

¿Intentaste usar - removeObjectForKey?

 [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"defunctPreference"];
sbooth
fuente
Saludos sbooth. Muy apreciado.
TonyNeallon
55
¿Alguna forma de eliminar objetos para todas las claves existentes?
samvermette
2
Si bien entiendo que esto parece funcionar, ¿por qué defunctPreference no es un tipo de sistema definido constante? Seguramente estaría nervioso porque dejaría de funcionar algún día en el futuro.
David H
¿Tienes que sincronizar después?
Travis M.
30

Aquí está la respuesta en Swift:

let appDomain = NSBundle.mainBundle().bundleIdentifier!
NSUserDefaults.standardUserDefaults().removePersistentDomainForName(appDomain)
juliensaad
fuente
8
NSUserDefaults.standardUserDefaults().removePersistentDomainForName(NSBundle.mainBundle().bundleIdentifier!)one-liner
Grace Shao
3
O más seguro:if let domainName = NSBundle.mainBundle().bundleIdentifier { NSUserDefaults.standardUserDefaults().removePersistentDomainForName(domainName) }
Valentin Shergin
1
Versión Swift 4 de la línea de Grace:UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!)
Carsten Hagemann
28

Si lo necesita durante el desarrollo, también puede restablecer su simulador, eliminando todo NSUserDefaults.

Simulador de iOS -> Restablecer contenido y configuración ...

Tenga en cuenta que también eliminará todas las aplicaciones y archivos en el simulador.

Roger Sanoli
fuente
15
NSDictionary *defaultsDictionary = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation];
for (NSString *key in [defaultsDictionary allKeys]) {
                    [[NSUserDefaults standardUserDefaults] removeObjectForKey:key];
}
folse
fuente
7

En Swift:

let defaults = NSUserDefaults.standardUserDefaults()
defaults.dictionaryRepresentation().keys.forEach { defaults.removeObjectForKey($0) }
Adam Waite
fuente
6

Nota: Esta respuesta también se ha actualizado para Swift.

¿Qué hay de tenerlo en una línea?

Ampliando la respuesta de @ Christopher Rogers: la aceptada.

[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];

y sí, en algún momento puede necesitarlo synchronize,

[[NSUserDefaults standardUserDefaults] synchronize];

He creado un método para hacer esto,

- (void) clearDefaults {
    [[NSUserDefaults standardUserDefaults] removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

Swift ?

Con Swift es aún más fácil.

extension UserDefaults {
    class func clean() {
        guard let aValidIdentifier = Bundle.main.bundleIdentifier else { return }
        standard.removePersistentDomain(forName: aValidIdentifier)
        standard.synchronize()
    }
}

Y uso :

UserDefaults.clean()
Hemang
fuente
6

Me encantan las extensiones cuando hacen que el código sea más limpio:

extension NSUserDefaults {
    func clear() {
        guard let domainName = NSBundle.mainBundle().bundleIdentifier else {
            return
        }

        self.removePersistentDomainForName(domainName)
    }
}

Swift 5

extension UserDefaults {
    func clear() {
        guard let domainName = Bundle.main.bundleIdentifier else {
            return
        }
        removePersistentDomain(forName: domainName)
        synchronize()
    }
}
Valentin Shergin
fuente
2

Todas las respuestas anteriores son muy relevantes, pero si alguien aún no puede restablecer los valores predeterminados del usuario para la aplicación eliminada, puede restablecer la configuración de contenido de su simulador y funcionará.ingrese la descripción de la imagen aquí

iDevAmit
fuente
2

Es un error o lo que sea, pero removePersistentDomainForNameno funciona mientras se borran todos los NSUserDefaultsvalores.

Por lo tanto, una mejor opción es restablecer el PersistentDomainy que puede hacerlo de la siguiente manera:

NSUserDefaults.standardUserDefaults().setPersistentDomain(["":""], forName: NSBundle.mainBundle().bundleIdentifier!)
Sohil R. Memon
fuente
1

Ampliando la respuesta de @ folse ... Creo que una implementación más correcta sería ...

NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
NSDictionary *defaultsDictionary = [[NSUserDefaults standardUserDefaults] persistentDomainForName: appDomain];
    for (NSString *key in [defaultsDictionary allKeys]) {
      NSLog(@"removing user pref for %@", key);
      [[NSUserDefaults standardUserDefaults] removeObjectForKey:key];
    }

... llamando al método persistentDomainForName de NSUserDefault: método. Como dicen los documentos, el método "Devuelve un diccionario que contiene las claves y los valores en el dominio persistente especificado". Llamar a dictionaryRepresentation: en su lugar, devolverá un diccionario que probablemente incluirá otras configuraciones según se aplique a un alcance más amplio.

Si necesita filtrar alguno de los valores que se van a restablecer, iterar sobre las claves es la forma de hacerlo. Obviamente, si desea eliminar todas las preferencias de la aplicación sin tener en cuenta, entonces uno de los otros métodos publicados anteriormente es el más eficiente.

markeissler
fuente
0

Prueba esto, está funcionando para mí.

Sola línea de código

[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];
Jaywant Khedkar
fuente