Menghapus NSUserDefaults

285

Saya menggunakan +[NSUserDefaults standardUserDefaults]untuk menyimpan pengaturan aplikasi. Ini terdiri dari sekitar selusin nilai string. Apakah mungkin untuk menghapus nilai-nilai ini secara permanen daripada hanya mengaturnya ke nilai default?

TonyNeallon
sumber

Jawaban:

514

Anda dapat menghapus domain persisten aplikasi seperti ini:

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

Dalam Swift 3 dan yang lebih baru:

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

Ini mirip dengan jawaban oleh @samvermette tetapi sedikit lebih bersih IMO.

Christopher Rogers
sumber
Ini berhasil, terima kasih! Jangan lupa untuk melepaskan appDomain sesudahnya.
IcyBlueRose
15
@IcyBlueRose - bundleIdentifier adalah objek autoreleased karena tidak dimulai dengan init atau baru, sehingga Anda akan melepaskannya secara berlebihan.
Christopher Rogers
1
Senang tahu, terima kasih! Tapi saya sedang berbicara tentang string appDomain. Apakah itu otomatis dirilis juga?
IcyBlueRose
2
@IcyBlueRose Objek yang dikembalikan oleh bundleIdentifier sama dengan objek yang dirujuk oleh appDomain.
Christopher Rogers
2
Saya sepertinya tidak bisa mengaktifkan ini pada 10.8 lagi, bisakah seseorang mengonfirmasi bahwa ini berhasil? Berikut pertanyaan SO terkait: stackoverflow.com/questions/13595415/…
DaGaMs
102

Kode ini mengatur ulang default ke domain pendaftaran:

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

Dengan kata lain, itu removeObjectForKeyuntuk setiap kunci tunggal yang pernah Anda daftarkan di aplikasi itu.

Penghargaan untuk Ken Thomases di utas Forum Pengembang Apple ini .

samvermette
sumber
4
Terima kasih banyak. Mengapa [NSUserDefaults resetStandardUserDefaults]tidak melakukan ini di luar jangkauan saya.
jakeboxer
2
@jboxer Saya baru saja menghabiskan waktu mempelajari dokumentasi Apple dan mengatur ulangStandardUserDefaults pada dasarnya membersihkan buffer di dalam memori ke disk dan menghapusnya. Jadi lain kali Anda mencoba mengambil nilai itu harus mengambilnya dari disk. NSManagedObjectContext dari Core Data juga menggunakan terminologi "reset" yang serupa.
Christopher Rogers
2
Ups, maksud saya menghapus buffer di memori tanpa menuliskannya ke disk. Jadi setiap perubahan yang Anda buat sebelum sinkronisasi ke disk akan hilang.
Christopher Rogers
4
Christopher, saya pikir Anda memilikinya mundur walaupun mungkin semuanya berubah. resetStandardUserDefaults adalah panggilan paling membingungkan yang pernah saya lihat di iOS. Apple Documents mengatakan "Menyinkronkan setiap perubahan yang dilakukan pada objek default pengguna bersama dan melepaskannya dari memori." jadi itu harus benar-benar disebut flushAndReleaseStandardUserDefaults. Saya meluangkan waktu untuk mengomentari komentar lama karena saya baru saja tertangkap oleh panggilan ini dan ingin menghindari orang lain dibakar (sekarang saya harus memberi tahu klien bahwa saya perlu memperbarui 90 aplikasi).
Andy Dent
97

Apakah Anda mencoba menggunakan - removeObjectForKey?

 [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"defunctPreference"];
sbooth
sumber
Cheers sbooth. Banyak Dihormati.
TonyNeallon
5
Adakah cara untuk menghapus objek untuk semua kunci yang ada?
samvermette
2
Sementara saya mengerti ini tampaknya berfungsi, mengapa tidak defunctPreference semacam sistem yang didefinisikan konstan? Saya yakin akan gugup bahwa ini akan berhenti bekerja suatu saat nanti.
David H
Apakah Anda harus melakukan sinkronisasi setelah?
Travis M.
30

Inilah jawabannya di Swift:

let appDomain = NSBundle.mainBundle().bundleIdentifier!
NSUserDefaults.standardUserDefaults().removePersistentDomainForName(appDomain)
juliensaad
sumber
8
NSUserDefaults.standardUserDefaults().removePersistentDomainForName(NSBundle.mainBundle().bundleIdentifier!)one-liner
Grace Shao
3
Atau lebih aman:if let domainName = NSBundle.mainBundle().bundleIdentifier { NSUserDefaults.standardUserDefaults().removePersistentDomainForName(domainName) }
Valentin Shergin
1
Versi cepat dari Grace's oneliner:UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!)
Carsten Hagemann
28

Jika Anda membutuhkannya saat mengembangkan, Anda juga dapat mengatur ulang simulator Anda, menghapus semua NSUserDefaults.

iOS Simulator -> Setel Ulang Konten dan Pengaturan ...

Ingatlah bahwa itu juga akan menghapus semua aplikasi dan file pada simulator.

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

Dalam Swift:

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

Catatan: Jawaban ini telah diperbarui untuk Swift juga.

Bagaimana kalau memilikinya di satu baris?

Extending @Christopher Rogers menjawab - yang diterima

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

dan ya, kadang-kadang Anda mungkin perlu synchronize,

[[NSUserDefaults standardUserDefaults] synchronize];

Saya telah membuat metode untuk melakukan ini,

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

Cepat ?

Dengan cepat bahkan lebih mudah.

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

Dan penggunaan :

UserDefaults.clean()
Hemang
sumber
6

Saya suka ekstensi ketika mereka membuat kode lebih bersih:

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

        self.removePersistentDomainForName(domainName)
    }
}

Cepat 5

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

Aku menemukan ini:

osascript -e 'tell application "iOS Simulator" to quit'
xcrun simctl list devices | grep -v '^[-=]' | cut -d "(" -f2 | cut -d ")" -f1 | xargs -I {} xcrun simctl erase "{}"

Sumber: https://gist.github.com/ZevEisenberg/5a172662cb576872d1ab

Daniel Gomez Rico
sumber
2

Semua jawaban di atas sangat relevan, tetapi jika seseorang masih tidak dapat mengatur ulang kesalahan pengguna untuk aplikasi yang dihapus, maka Anda dapat mengatur ulang pengaturan konten simulator Anda, dan itu akan berhasil.masukkan deskripsi gambar di sini

iDevAmit
sumber
2

Ini bug atau apa pun tetapi removePersistentDomainForNametidak berfungsi saat membersihkan semua NSUserDefaultsnilai.

Jadi, pilihan yang lebih baik adalah mengatur ulang PersistentDomaindan yang dapat Anda lakukan melalui cara berikut:

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

Memperluas jawaban @ folse ... Saya yakin implementasi yang lebih tepat adalah ...

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];
    }

... memanggil metode persistentDomainForName: NSUserDefault. Sebagai status dokumen, metode "Mengembalikan kamus yang berisi kunci dan nilai dalam domain persisten yang ditentukan." Calling dictionaryRepresentation: sebagai gantinya, akan mengembalikan kamus yang kemungkinan akan mencakup pengaturan lain yang berlaku untuk cakupan yang lebih luas.

Jika Anda perlu menyaring salah satu nilai yang harus diatur ulang, maka iterasi tombol adalah cara untuk melakukannya. Tentunya, jika Anda ingin mengabaikan semua prefs untuk aplikasi tanpa memperhatikan, maka salah satu metode lain yang diposting di atas adalah yang paling efisien.

markeissler
sumber
0

Coba ini, Ini bekerja untuk saya.

Baris kode tunggal

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