【问题标题】:UserDefault with nsmutabledictionary could not cast value of type '__NSSingleEntryDictionaryI' to NSMutableDictionary带有 nsmutabledictionary 的 UserDefault 无法将“__NSSingleEntryDictionaryI”类型的值转换为 NSMutableDictionary
【发布时间】:2020-03-04 07:06:12
【问题描述】:

Ios 开发新手。目前是一个返回 NSMutableDictionary 的函数,它存储在 userDefaults 中。但是,当我从 userdefault 检索值时,它返回的 NSMutableDictionary 格式不正确,它无法解析 NSMutableDictionary 并返回错误“无法将 '__NSSingleEntryDictionaryI' 类型的值转换为 NSMutableDictionary”。

返回 NSMutableDictionary 的函数

func initializeStructureOfControl () -> NSMutableDictionary {
        var parentSlideControl = NSMutableDictionary()

        var slideControl = NSMutableDictionary()
        slideControl.setValue(NSMutableDictionary(), forKey: UserDefaultKeys.fdtControlKey)
        slideControl.setValue(NSMutableDictionary(), forKey: UserDefaultKeys.pdtControlsData)
        slideControl.setValue(NSMutableDictionary(), forKey: UserDefaultKeys.eeControlsData)
        slideControl.setValue(NSMutableDictionary(), forKey: UserDefaultKeys.fbeControlsData)

        parentSlideControl.setValue(slideControl, forKey: UserDefaultKeys.slideControlKey)

        return parentSlideControl

    }

在用户默认中初始化

UserDefaults.standard.setValue( initializeStructureOfControl(), forKey: UserDefaultKeys.slideControlKey)

检索值

UserDefaults.standard.object(forKey: UserDefaultKeys.slideControlKey)

userdefault 中保存的值:

  ▿ some : 1 element
    ▿ 0 : 2 elements
      ▿ key : slideControlsData
      ▿ value : 4 elements
        ▿ 0 : 2 elements
          - key : fbeControlsData
          - value : 0 elements
        ▿ 1 : 2 elements
          - key : eeControlsData
          - value : 0 elements
        ▿ 2 : 2 elements
          - key : fdtControlsData
          - value : 0 elements
        ▿ 3 : 2 elements
          - key : pdtControlsData
          - value : 0 elements

用户默认返回的值

▿ some : 1 element
    ▿ 0 : 2 elements
      ▿ key : slideControlsData
      ▿ value : 4 elements
        ▿ 0 : 2 elements
          - key : fbeControlsData
          - value : 0 elements
        ▿ 1 : 2 elements  
          - key : eeControlsData
          - value : 0 elements {.....}
        ▿ 2 : 2 elements 
          - key : fdtControlsData
          - value : 0 elements {.....}
        ▿ 3 : 2 elements  
          - key : pdtControlsData
          - value : 0 elements {.....}

虽然它在 ios 12 或之前的设备上工作(返回与保存相同的值)但在 ios 13 及更高版本上返回上述格式字符串,而不是在用户默认值中保存一个。

【问题讨论】:

  • 不要在 Swift 中使用 objective-c-ish NSMutable... 集合类型。并且不要使用setValue(forKey,除非你知道 KVC 是什么并且你真的需要 KVC。发生错误是因为您从未从 UserDefaultsobject(forKey 获得可变集合类型,即使在 Objective-C 中也没有。
  • 我应该用什么替代 NSMutableDictionary?因为目前整个应用程序都使用 NSMutableDictionary。
  • 使用 Swift 原生类型 [String:Any]。它以variable 的形式免费提供可变性。

标签: swift ios13 swift5


【解决方案1】:

错误

无法将“__NSSingleEntryDictionaryI”类型的值转换为 NSMutableDictionary

发生是因为object(forKey 返回一个im可变对象。例如,要获取可变字典,您必须创建一个新字典

var slideControl = NSMutableDictionary(dictionary: (UserDefaults.standard.object(forKey: UserDefaultKeys.slideControlKey) as! NSDictionary))

但是,在 Swift 中强烈建议不要使用所有 NS(Mutable)... 集合类型。这是原生版本

func initializeStructureOfControl () -> [String:Any] {
    let slideControl = [UserDefaultKeys.fdtControlKey : [String:Any](),
                        UserDefaultKeys.pdtControlsData : [String:Any](),
                        UserDefaultKeys.eeControlsData : [String:Any](),
                        UserDefaultKeys.fbeControlsData : [String:Any]()]
    return [UserDefaultKeys.slideControlKey : slideControl]
}

保存到UserDefaults

UserDefaults.standard.set(initializeStructureOfControl(), forKey: UserDefaultKeys.slideControlKey)

读一读

var slideControl = UserDefaults.standard.dictionary(forKey: UserDefaultKeys.slideControlKey)

字典是可变的variable。但考虑到 Swift 字典是值类型。您必须就地修改它。更有效的解决方案可能是自定义结构而不是字典和 Codable 协议以将对象保存在 UserDefaults 中。

【讨论】:

  • 感谢 vadian 我会将所有 NSMutableDictionary 更改为 [String:Any]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-30
  • 2016-10-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多