Search code examples
iosswiftdictionaryuserdefaults

Attempt to insert non-property list object error while storing dictionary in userdefaults


I have a dictionary with type of [Int: [Int]], I want to store it in user default. The key of dictionary is like that : 1100110004 and the value:

[1,2,0,0]

But I got this error:

Attempt to insert non-property list object {\n 1100110004 = (\n 1,\n 2,\n 0,\n 0\n );\n} for key visibleChart1100110004"

here is my code:

let userDefaults = UserDefaults.standard

private lazy var visibleChartDictionary = [Int: [Int]]()

and in a function:

visibleChartDictionary = [id :  convertChartTypetoInt(chartType: visibleCharts)]

 chartUserDefaults.set(visibleChartDictionary, forKey: "visibleChart\(id)")

There is a function here to convert a data model to Int (I read that I cant store a data model type in user defaults)

func convertChartTypetoInt(chartType:[ChartType]) -> [Int] {
      var chartTypeInt: [Int] = [0, 0 , 0, 0]

      let ecgNumber = 1
      let respiratoryNumber = 2
      let bodyTempNumber = 3
      let activityNumber = 4

      //ecg
      if let index = chartType.firstIndex(where: {$0 == .ecg}) {
         chartTypeInt.remove(at: index)
         chartTypeInt.insert(ecgNumber, at: index)
      }

      //respiratory
      if let index = chartType.firstIndex(where: {$0 == .respiratory}) {
         chartTypeInt.remove(at: index)
         chartTypeInt.insert(respiratoryNumber, at: index)
      }

      //body temp
      if let index = chartType.firstIndex(where: {$0 == .bodyTemp}) {
         chartTypeInt.remove(at: index)
         chartTypeInt.insert(bodyTempNumber, at: index)
      }

      //activity
      if let index = chartType.firstIndex(where: {$0 == .activity}) {
         chartTypeInt.remove(at: index)
         chartTypeInt.insert(activityNumber, at: index)
      }
      return chartTypeInt
   }

could any one help me on this?


Solution

  • User defaults is a property list. Property list dictionaries must have string keys.

    You can always test the eligibility of something to be put directly into User Defaults like this:

    let d : [Int:[Int]] = [1100110004 : [1,2,0,0]]
    do {
        let data = try PropertyListSerialization.data(
            fromPropertyList: d, format: .binary, options: 0)
    } catch { print(error) }
    

    A simple and obvious solution: your d is Codable, so encode it to a property list and store the resulting Data object in user defaults.

    let d : [Int:[Int]] = [1100110004 : [1,2,0,0]]
    do {
        let data = try PropertyListEncoder().encode(d)
        // and store `data` in user defaults
    } catch { print(error) }