stringForKey се срива в приложението

Опитвам се да съхраня низ в NSUserDefaults, но когато отида да го извлека, приложението ми се срива.

Предполагам, че това се случва само първия път, тъй като никога не е задавана стойност за този ключ в NSUserDefaults, но се опитах да добавя някакъв код в viewDidLoad(), за да го задам за първи път и това не изглежда да помага.

Ето моят код:

override func viewDidLoad() {
    super.viewDidLoad()

    itemSelected = "Moss"
    NSUserDefaults.standardUserDefaults().setObject(itemSelected, forKey: "colourChosen")
}

override func viewWillAppear(animated: Bool) {
    itemSelected = NSUserDefaults.standardUserDefaults().stringForKey("colourChosen")!
}

func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    itemSelected = colours[row]
    NSUserDefaults.standardUserDefaults().setObject(itemSelected, forKey: "colourChosen")
}

Приложението се срива в viewWillAppear()

Някой има ли идеи?


person user3746428    schedule 18.11.2014    source източник


Отговори (1)


Не извиквате synchronize() след настройка на обекта:

let userDefaults = NSUserDefaults.standardUserDefaults()
userDefaults.setObject(itemSelected, forKey: "colourChosen")
userDefaults.synchronize()
             ^^^^

Без това никаква промяна не се записва веднага. Това може да е причината.

synchronize трябва да се извиква всеки път, когато правите промени в потребителските настройки по подразбиране и искате незабавно да запазите промените (системата автоматично го извиква на определени интервали от време).

Въпреки това във вашата реализация viewWillAppear забелязвам, че използвате принудително разгръщане, което винаги трябва да избягвате, освен ако не сте 100% сигурни, че незадължителното действително съдържа стойност, различна от нула. Бих защитил това разопаковане с незадължително обвързване:

if let colour = NSUserDefaults.standardUserDefaults().stringForKey("colourChosen") {
    itemSelected = color
}

Актуализация

Забелязвам, че itemSelected е временен контейнер за това, което съхранявате в потребителските настройки по подразбиране. Може да помислите за преместване на потребителския код по подразбиране в изчислено свойство, за да предотвратите дублиране на код всеки път, когато това свойство се чете или променя - нещо като:

private var _itemSelected : String?

var itemSelected : String? {
    get {
        if _itemSelected == nil {
            _itemSelected = NSUserDefaults.standardUserDefaults().stringForKey("colourChosen")
        }
        return _itemSelected
    }
    set {
        let userDefaults = NSUserDefaults.standardUserDefaults()
        userDefaults.setObject(newValue, forKey: "colourChosen")
        userDefaults.synchronize()
    }
}

където _itemSelected е просто кеширана стойност - или подобна реализация, но без кешираната стойност:

var itemSelected : String? {
    get {
        return NSUserDefaults.standardUserDefaults().stringForKey("colourChosen")
    }
    set {
        let userDefaults = NSUserDefaults.standardUserDefaults()
        userDefaults.setObject(newValue, forKey: "colourChosen")
        userDefaults.synchronize()
    }
}

Имайте предвид, че и в двата случая типът свойство е незадължителен низ

person Antonio    schedule 18.11.2014
comment
Това не е проблемът за съжаление. Сигурни ли сте, че трябва да използвате synchronise()? Използвал съм NSUserDefaults много пъти и никога не ми се е налагало да го използвам преди. - person user3746428; 18.11.2014
comment
Той се извиква автоматично на периодични интервали, но ако искате промените да бъдат незабавно достъпни, е по-добре да го използвате. Това може да е вашият случай, въпреки че не решава проблема. Можете ли да публикувате във въпроса си какво изключение имате? - person Antonio; 18.11.2014
comment
Не забелязах ! в края на реда в viewWillAppear. Това прави принудително разгръщане и най-вероятно е причината за изключението, ако ключът не съществува. Предлагам да обвиете това в незадължително обвързване - person Antonio; 18.11.2014
comment
Благодаря много! Бях на път да отговоря, за да кажа, че нито едно от решенията не работи, но имах несвързан проблем. - person user3746428; 18.11.2014