2016-02-03 1 views
1

Я не понимаю, почему я получаю сообщение об ошибке по этому методу:Не удается обновить NSMutableDictionary?

let loginCountKey = "loginCount" 
let appReviewParamsKey = "appReviewParams" 

func resetLoginCount() { 
    let defaults = NSUserDefaults.standardUserDefaults() 

    if let reviewParameters = defaults.valueForKey(appReviewParamsKey) as? NSMutableDictionary { 
     reviewParameters[loginCountKey] = 1 

     defaults.setObject(reviewParameters, forKey: appReviewParamsKey) 
     defaults.synchronize() 
    } 
} 

SetObject линия дает мне ошибку: caught "NSInternalInconsistencyException", ... mutating method sent to immutable object"

При отладке, reviewParameters показывает как NSMutableDictionary. Я также попробовал, если var вместо if if let (это не должно быть лишним) и получил ту же ошибку.

Я также попытался установить значение NSNumber (междунар: 1) вместо того, чтобы просто 1.

Почему это вызовет данную ошибку?

+0

Посмотрите на http://stackoverflow.com/questions/5790715/mutating-method-sent-to-immutable-object – ChrisH

+0

@ChrisH Спасибо! –

+0

Не беспокойтесь. Это стало для меня неожиданностью. – ChrisH

ответ

1

Есть два вопроса:

  • NSUserDefaults возвращает неизменные объекты, когда отливают тип Foundation
  • Даже если возвращаемое значение было изменчивым вы назначили его постоянный (пусть), что делает объект неизменяемый в Swift ,

В Swift рекомендуемый способ заключается в использовании нативного Swift типы и переменных (VAR), например

func resetLoginCount() { 
    let defaults = NSUserDefaults.standardUserDefaults() 

    if var reviewParameters = defaults.objectForKey(appReviewParamsKey) as? [String:AnyObject] { 
    reviewParameters[loginCountKey] = 1 

    defaults.setObject(reviewParameters, forKey: appReviewParamsKey) 
    defaults.synchronize() 
    } 
} 
1

NSUserDefaults.objectForKey (который общий метод КВЦ valueForKey должен вызывать через к) возвращает неизменный NSDictionary, когда он находит данные словарного формата для этого ключа по умолчанию.

Использование as? является литой, не преобразования. То есть вы говорите Swift, чтобы интерпретировать словарь у вас есть , как если бы он былNSMutableDictionary (хотя это не так, поэтому это не удается). Если вы хотите, чтобы конвертировать a NSDictionary в NSMutableDictionary, вам нужно создать экземпляр последнего из прежнего (с mutableCopy или initWithDictionary:).

Но вам даже не нужно работать со словарями Foundation здесь - NSDictionary автоматически соединяется с Swift-словарем, и вы можете использовать его для интерпретации as правых клавиш/значений. И вы можете связать необязательный как изменяемые значения с помощью if var вместо if let:

if var reviewParameters = defaults.objectForKey(appReviewParamsKey) as? [String: Int] { 
    reviewParameters[loginCountKey] = 1 

    defaults.setObject(reviewParameters, forKey: appReviewParamsKey) 
    defaults.synchronize() 
}