Intereting Posts
Получение текущей фоновой операции и ее обработка Обновить пользовательский интерфейс при изменении настроек – Objective-C ScrollviewDidScroll не вызывается в каждой точке Недопустимый контекст 0x0 с FBSDKProfilePictureView UITableView didSelect делегат не вызван? Хранение изображений в основных данных, как очистить кеш? Воспроизведение композиций случайным образом из моего Mutable Array Основные данные сохраняют только около 50% времени Могу ли я перенести приложения iOS с истекшей учетной записи разработчика на другую активную? Не удалось зарегистрировать мое устройство ios для разбора для push-уведомлений NSSearchPathForDirectoriesInDomains дает EXC_BREAKPOINT Запуск приложения IOS в фоновом режиме нового разработчика ios определяет, как запускается приложение Проблема с распространением iOS 8 Framework при загрузке в магазине приложений Как поместить ссылку на тег <div> в IOS

Постоянная NSUserDefault не обновляется

У меня есть NSUserDefaults реализованные в моем приложении, и правильные значения сохраняются между запусками, но при ссылке на константу, которую я создал, значения не обновляются, когда значения по умолчанию меняются во время сеанса.

Я уверен, что моя проблема связана с использованием констант для ссылки на NSUserDefaults , но я вижу, сколько кода оно меня спасло, и я хотел бы придерживаться этого подхода, если это возможно / хорошая практика. Я не уверен, как мне нужно обновлять константу для новых значений NSUserDefault . Я не получаю сбоев – просто устаревшие значения.

Моя настройка

AppDelegate.swift

Я использую NSUserDefaults для хранения целочисленных значений в моем приложении. В AppDelegate.swift я проверяю, установлены ли они. Это работает.

PreferencesViewController.swift

У меня есть PreferencesVC который я настроил, который заполняется по умолчанию и позволяет пользователю изменять значения по умолчанию. Я поставил некоторые операторы print чтобы проверить новые значения NSUserDefaults когда они сохранены. Это работает.

MyTableViewController.swift Я объявил константы на a, чтобы я мог обрезать подробный код.

 // Import Statements @import UIKit // Constants I declare here so they're accessible throughout the app. let kDefaultActiveTime = NSUserDefaults.standardUserDefaults().integerForKey("defaultActiveTime") let kDefaultBreakTime = NSUserDefaults.standardUserDefaults().integerForKey("defaultBreakTime") let kDefaultRounds = NSUserDefaults.standardUserDefaults().integerForKey("defaultRounds") // Class declaration class MyTableViewController: UITableViewController 

В моей cellForRowAtIndexPath я использую константы по умолчанию для вычисления времени и вывод строки для метки в ячейке. Вот строка:

  // boilerplate cellForRowAtIndexPath omitted let customCell = tableView.dequeueReusableCellWithIdentifier("customCell", forIndexPath: indexPath) as! RoutineSelectionTableViewCell let routine = fetchedResultsController.objectAtIndexPath(indexPath) as! SavedRoutines // ** This doesn't update w/ tableView.reloadData() customCell.routineInformationLabel.text = String(format: "Time to complete - %@", formatTimeInSeconds(totalRoutineTime(routine.items! as NSOrderedSet))) 

Вот методы, используемые для создания строки для routineInformationLabel.text :

 // Time computation methods func totalRoutineTime(routine: NSOrderedSet) -> Int { var totalRounds = 0 for item in routine { // get the total of rounds totalStretchRounds += (((item as! MyNSManagedObject).sideMultiplier?.integerValue)!) * kDefaultRounds } let totalActiveTime = totalRounds * kDefaultActiveTime let totalBreakTime = (totalRounds - 1) * kDefaultBreakTime // subtract 1 rest period for last item return totalActiveTime + totalBreakTime } func formatTimeInSeconds(totalSeconds: Int) -> String { let seconds = totalSeconds % 60 let minutes = (totalSeconds / 60) % 60 let hours = totalSeconds / 3600 let stringHours = hours > 9 ? String(hours) : "0" + String(hours) let stringMinutes = minutes > 9 ? String(minutes) : "0" + String(minutes) let stringSeconds = seconds > 9 ? String(seconds) : "0" + String(seconds) if hours > 0 { return "\(stringHours):\(stringMinutes):\(stringSeconds)" } else { return "\(stringMinutes):\(stringSeconds)" } } 

Я попытался создать наблюдателя для перезагрузки tableView при сохранении NSUserDefaults , но это, похоже, не делает трюк. Я также пытался бросить в tableView.reloadData() в viewDidAppear , viewWillAppear и т. viewDidAppear viewWillAppear большой удачи.

Спасибо за чтение. Я приветствую ваши предложения.

Похоже, что все константы действительно дают вам немного более чистый, читаемый код. Я бы рекомендовал писать частные вспомогательные функции в классе, чтобы сделать то же самое. Чтение и удаление NSUserDefaults довольно быстро и не должно представлять проблемы. Я также согласен с комментариями к другому ответу, нет необходимости синхронизировать. Обычно это рекомендуется. Пусть система iOS справится с этим для вас. Это много способно это сделать. Синхронизация значений по умолчанию записывает их на диск, он будет делать это, когда он будет готов. В противном случае он будет хранить и читать данные из памяти.

Я не вижу вопиющих ошибок в показанном вами коде, но я думаю, что в какой-то момент значения по умолчанию обновляются, а константы уже установлены. Таким образом, в принципе, они никогда не будут установлены снова, как только класс будет загружен.

Чтобы получить значения более сжатым, легко типизированным образом, рассмотрите частную функцию, например:

 private func getDefaultRounds() -> Int { return NSUserDefaults.standardUserDefaults().integerForKey("defaultRounds") } 

Который можно получить в любом месте в классе с помощью только getDefaultRounds()

Я принял решение Кайла, но я немного экспериментировал как учебное упражнение, и я бросаю это, чтобы понять, что люди думают:

Вместо того, чтобы повторно вводить код, помните, что такое мой ключ, будь то Int , Float или Bool и т. Д., Я создал Struct для доступа к значениям:

 struct Defaults { let activeTime = NSUserDefaults.standardUserDefaults().integerForKey("defaultActiveTime") let breakTime = NSUserDefaults.standardUserDefaults().integerForKey("defaultBreakTime") let rounds = NSUserDefaults.standardUserDefaults().integerForKey("defaultRounds") } 

Когда мне нужно получить доступ к значениям NSUserDefaults , они обновляются динамически. Кажется, они объявляют их постоянными «моментальными снимками» во времени, но они не обновляются.

Когда мне нужно по умолчанию, и я не хочу вводить их, я печатаю:

 Defaults().rounds Defaults().activeTime Defaults().breakTime по Defaults().rounds Defaults().activeTime Defaults().breakTime по Defaults().rounds Defaults().activeTime Defaults().breakTime 

Я не наткнулся на какие-то «зачистки» с этим подходом … пока. Если у кого-то есть предложения по улучшению этого, я все уши.