saving swifty json array to user defaults
Asked Answered
W

4

5

i have a json data which gives the following information:

let data = [
  {
    "QuestionTitle" : "Entomology is the science that studies",
    "Id" : 205,
    "Options" : [
      { "Option" : "Insects", "Id" : 810 },
      { "Option" : "The origin and history of technical and scientific terms", "Id" : 811 },
      { "Option" : "The formation of rocks", "Id" : 812 },
      { "Option" : "Behavior of human beings", "Id" : 809 }
    ]
  },
  {
    "QuestionTitle" : "A train running at the speed of 60 km\/hr crosses a pole in 9 seconds. What is the length of the train?",
    "Id" : 199,
    "Options" : [
      { "Option" : "120 metres", "Id" : 785 },
      { "Option" : "324 metres", "Id" : 787 },
      { "Option" : "180 metres", "Id" : 786 },
      { "Option" : "150 metres", "Id" : 788 }
    ]
  }
]

I am using swiftyjson. I want to save the entire array using nsuserdefaults.

GlobalVar.defaults.set(json, forKey: "questionArray")
GlobalVar.defaults.synchronize()

However, I get an error

"[User Defaults] Attempt to set a non-property-list object".

Please assist i am new to swift. I have also checked other similar questions but seems to not work.

Woad answered 2/8, 2017 at 9:56 Comment(2)
try setObject(json.object, forKey: "questionArray")Vive
You can only save objects to UserDefaults that are property list types. In order to save a custom class/object, you need to convert it to NSData by archiving it. See this answerInvertebrate
C
4

You cannot save SwiftyJSON's custom type JSON to UserDefaults but you can save the raw array because a deserialized JSON collection type is property list compliant.

Just call arrayObject on the JSON object:

GlobalVar.defaults.set(json.arrayObject, forKey: "questionArray")
Conglomerate answered 2/8, 2017 at 10:11 Comment(5)
thank you for that. but i tried with json.arrayObject. And it worked.Woad
i tried with json.arrayValue and it was giving me the above error.Woad
You are right, my bad, I mixed up the types and edited the answer.Conglomerate
its okay :) after adding the json object to nsuserdefault i tried to retrieve it using: let questionObject = GlobalVar.defaults.array(forKey: "questionArray") I got back my original json array. Then, I did: for questionDict in questionObject! { lblQuestion.text = questionDict["QuestionTitle"] } However, this gives me an error stating: "Type 'Any' has no subscript members"Woad
You have to downcast the types GlobalVar.defaults.array(forKey: "questionArray") as! [[String:Any]] and lblQuestion.text = questionDict["QuestionTitle"] as! String. And be aware that the app will crash if you retrieve the array before saving it once.Conglomerate
K
3

Swift 3.0

You can save SwiftyJSON custom type data as like below.

guard let rawData = try? json.rawData() else { return }
UserDefaults.standard.setValue(rawData, forKey: "Your_key")

And, To retrieve JSON data from UserDefaults, you can do like this way.

guard let data = UserDefaults.standard.value(forKey: "Your_key") as? Data else { return }

let json = JSON(data) 
Knighterrantry answered 2/8, 2017 at 10:41 Comment(1)
Why do you use KVC to set and get the value? Is there a particular reason?Conglomerate
H
1

You can't save the array of dictionary directly to the NSUserDefault, You need to convert the object of array into NSData

See more for help:

Attempt to set a non-property-list object as an NSUserDefaults

Holub answered 2/8, 2017 at 10:7 Comment(0)
A
0

Swift 4.0 | Xcode 9.1 | SwiftyJSON

We can save array of dictionary directly, no problem. Only, the problem is, how to retrieve it?

It barely downcast to array of dictionary (say [[String : Any]]). for this, we required SwiftyJSON pods import SwiftyJSON // Don't forget this

let arrayOfDictionary = [
                         { 
                           "VersionNumber" : "1.0.0.0", 
                                  "FormID" : "18"
                          },
                         {
                           "VersionNumber" : "1.0.0.3",
                                  "FormID" : "19"
                          }
                         ]

Saving it directly to UserDefaults like :

UserDefaults.standard.set(saveFormDetails, forKey: "FormDetails")

Retrieving from UserDefaults :

let savedFormDetailsData = JSON.init(rawValue:UserDefaults.standard.array(forKey: "FormDetails"))

Now, savedFormDetailsData is the array of dictionary back [PropertyList Type], for further we do :

for form in 0..<arrayOfDictionary.count {
    print("FormID :", savedFormDetailsData?[form]["FormID"]) 
    print("VersionNumber :", savedFormDetailsData?[form]["VersionNumber"])
}
Anticathode answered 8/12, 2017 at 11:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.