Очищення параметрів NSUserDefaults


285

Я використовую +[NSUserDefaults standardUserDefaults]для зберігання налаштувань програми. Складається приблизно з десятка значень рядків. Чи можна назавжди видалити ці значення, а не просто встановити їх за замовчуванням?


Відповіді:


514

Ви можете видалити постійний домен програми так:

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

У Swift 3 та пізніших версіях:

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

Це схоже на відповідь @samvermette, але трохи чистіше IMO.


Це спрацювало чудово, дякую! Просто не забудьте згодом випустити appDomain.
IcyBlueRose

15
@IcyBlueRose - bundleIdentifier - це об'єкт, що опублікований автоматично, оскільки він не починається з init або new, тому ви перезапустите його.
Крістофер Роджерс

1
Рада знати, дякую! Але я говорив про рядок appDomain. Це авто також випущено?
IcyBlueRose

2
@IcyBlueRose Об'єкт, що повертається bundleIdentifier, такий самий, як об'єкт, на який посилається appDomain.
Крістофер Роджерс

2
Я не можу зробити так, щоб це працювало на 10.8 більше, хтось може, будь ласка, підтвердити, що це працює? Ось пов'язаний з цим питання SO: stackoverflow.com/questions/13595415 / ...
DaGaMs

102

Цей код скидає за замовчуванням реєстраційний домен:

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

Іншими словами, це removeObjectForKeyдля кожного ключа, який ви коли-небудь зареєстрували в цьому додатку.

Кредити Кену Томасе на цій темі Форумів розробників Apple .


4
Дякую купу. Чому [NSUserDefaults resetStandardUserDefaults]цього не зробити, це поза мене.
Джейкбоксер

2
@jboxer Я просто витратив деякий час на вивчення документації Apple і resetStandardUserDefaults, в основному, промиває буфер пам'яті на диску і витирає його з очищення. Тож наступного разу, коли ви намагатиметеся отримати значення, воно має схопити його з диска. NSManagedObjectContext Core Data також використовує аналогічну "скидання" термінології.
Крістофер Роджерс,

2
На жаль, я мав на увазі, що він витирає буфер пам'яті, не записуючи його на диск. Таким чином, будь-які зміни, внесені до синхронізації на диску, будуть втрачені.
Крістофер Роджерс

4
Крістофере, я думаю, ти маєш це назад, хоча, можливо, все змінилося. resetStandardUserDefaults - це найбільш заплутано названий дзвінок, який я бачив поки що в iOS. В Apple Docs кажуть, що "Синхронізує будь-які зміни, внесені до об'єкта спільного користувачем за замовчуванням, і звільняє його з пам'яті". тому його справді слід назвати flushAndReleaseStandardUserDefaults. Я витрачаю час, щоб прокоментувати старий коментар, тому що мене просто зачепило цей дзвінок і хочу, щоб хтось інший не спалювався (мені зараз потрібно сказати клієнту, що мені потрібно оновити 90 додатків).
Енді Дент

97

Ви спробували використовувати - removeObjectForKey?

 [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"defunctPreference"];

Ура кубо. Цінується.
TonyNeallon

5
Будь-який спосіб видалити об’єкт для всіх існуючих ключів?
samvermette

2
Хоча я розумію, це, здається, працює, чому не defunctPreference якась система, визначена константа? Я був би впевнений, що нервує, колись у майбутньому це перестане працювати.
Девід Н

Чи потрібно синхронізувати після?
Травіс М.

30

Ось відповідь у Swift:

let appDomain = NSBundle.mainBundle().bundleIdentifier!
NSUserDefaults.standardUserDefaults().removePersistentDomainForName(appDomain)

8
NSUserDefaults.standardUserDefaults().removePersistentDomainForName(NSBundle.mainBundle().bundleIdentifier!)one-liner
Грейс Шао

3
Або безпечніше:if let domainName = NSBundle.mainBundle().bundleIdentifier { NSUserDefaults.standardUserDefaults().removePersistentDomainForName(domainName) }
Валентин Шергін

1
Swift 4 версія онлайнера Грейс:UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!)
Карстен

28

Якщо вам це потрібно під час розробки, ви також можете скинути ваш тренажер, видаливши всі NSUserDefaults.

iOS Simulator -> Скидання вмісту та налаштувань ...

Майте на увазі, що він також видалить усі програми та файли на тренажері.


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

7

У Свіфті:

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

6

Примітка. Ця відповідь оновлена ​​і для Swift.

А як бути з ним на одній лінії?

Розширена відповідь @Christopher Rogers - прийнята.

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

і так, колись вам це знадобиться synchronize,

[[NSUserDefaults standardUserDefaults] synchronize];

Я створив метод для цього,

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

Швидкий ?

Зі швидким його ще легше.

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

І використання :

UserDefaults.clean()

6

Я люблю розширення, коли вони роблять код чистішим:

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

        self.removePersistentDomainForName(domainName)
    }
}

Швидкий 5

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


2

Усі вищевказані відповіді дуже актуальні, але якщо хтось все ще не може скинути налаштування користувача для видаленого додатка, ви можете скинути налаштування вмісту вашого симулятора, і він спрацює.введіть тут опис зображення


2

Це помилка чи що завгодно, але removePersistentDomainForNameне працює при очищенні всіх NSUserDefaultsзначень.

Отже, кращий варіант полягає в тому, щоб скинути PersistentDomainі що ви можете зробити наступним чином:

NSUserDefaults.standardUserDefaults().setPersistentDomain(["":""], forName: NSBundle.mainBundle().bundleIdentifier!)

1

Розширення на відповідь @ folse ... Я вважаю, що більш правильним було б виконання ...

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

... виклик методу persistentDomainForName: NSUserDefault::. Як констатують документи, метод "Повертає словник, що містить ключі та значення у вказаному постійному домені." Виклик DictionaryRepresentation: натомість повертає словник, який, ймовірно, включає інші параметри, оскільки він застосовується до ширшої області застосування.

Якщо вам потрібно відфільтрувати будь-яке значення, яке потрібно скинути, це зробити це повторенням клавіш. Очевидно, що якщо ви хочете просто занурити всі префікси для програми без огляду, то один з інших способів, розміщених вище, є найбільш ефективним.


0

якщо налаштування програми, що потребує скидання, має nsuserdefault для доступу до мікрофона (мій випадок), просте рішення - відповідь від Ентоні МакКорміка ( Iphone - Як увімкнути доступ програми до медіа на пристрої? - ALAssetsLibraryErrorDomain Code = -3312 "Глобальний відхилений доступ" ).

на пристрої перейдіть у Налаштування> Загальне> Скидання> Скидання попереджень про місцезнаходження


0

Спробуйте це, це працює для мене.

Єдиний рядок коду

[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.