Why Swift 5 cannot parse plist file

Hello:


I have the file below that I am trying to get Swift to parse and do a readout of the file in the debug area but it is not parsing the file.


Here is the .json file that I converted to a .plist file with terminal plutil converter:

(I can't copy the plist file. Is there a way to copy it?)


[

{

"questionId":"359",

"difficulty_level":"80",

"subject":"MATH",

"question":"There are 5 children in the first row and 6 in the second row. All in the first row have pencils, and 2 in the second row have them. How many more pencils are needed?",

"distractor_1":"6",

"distractor_2":"3",

"distractor_3":"4",

"distractor_4":"11",

"distractor_5":"NH",

"answer":"3",

"id":"357",

"q_value":"1530",

"grade":"2",

"topic":"WORD PROBLEMS",

"qid":"1"

}

]


Here is the Swift Code:


mport Cocoa

import CoreData

import Foundation


class ViewController: NSViewController, NSApplicationDelegate {


var username: String = "Anonymous"


override func viewDidLoad() {

super.viewDidLoad()

preloadData()

// Do any additional setup after loading the view.

}


func preloadData() {

let preloadedDataKey = "didPreloadTest"

let userDefaults = UserDefaults.standard

if userDefaults.bool(forKey: preloadedDataKey) == false {

guard let urlPath = Bundle.main.url(forResource: "test1", withExtension: "plist") else{

return

}

if let arrayContents = NSArray(contentsOf: urlPath) as? [String] {

for scqName in arrayContents {

print (scqName)

}

}

}

}

}

Accepted Reply

Hello OOper:


That worked perfectly. It was a beautiful sight to see the results displayed correctly in the debug area.


I am also going to look at using .json files which is the format that all my DB files are in presently.

Replies

With testing with an old text-based plist, I have confirmed that `NSArray.init(contentsOf:)` fails:

( { "questionId"="359"; "difficulty_level"="80"; "subject"="MATH"; "question"="There are 5 children in the first row and 6 in the second row. All in the first row have pencils; and 2 in the second row have them. How many more pencils are needed?"; "distractor_1"="6"; "distractor_2"="3"; "distractor_3"="4"; "distractor_4"="11"; "distractor_5"="NH"; "answer"="3"; "id"="357"; "q_value"="1530"; "grade"="2"; "topic"="WORD PROBLEMS"; "qid"="1"; } )

It may work for other plist formats, but you should better not rely on it, as it is marked as deprecated.

You can try `PropertyListSerialization`:

    guard let url = Bundle.main.url(forResource: "test1", withExtension: "plist") else{
        print("no plist in bundle")
        return
    }
    print("found plist")
    do {
        let arrayData = try Data(contentsOf: url)
        guard let arrayContents = try PropertyListSerialization.propertyList(from: arrayData, format: nil) as? [Any] else {
            print("plist cannot be read as Array")
            return
        }
        
        for scqName in arrayContents {
            print (scqName)
        }
    } catch {
        print(error)
    }

If you can easily convert your plist to json, replacing the resource to json to use `JSONSerialization` or `Codable` would be a good plan.

Hello OOper:


That worked perfectly. It was a beautiful sight to see the results displayed correctly in the debug area.


I am also going to look at using .json files which is the format that all my DB files are in presently.

>That worked perfectly.


In that case, OOPER's reply is the correct answer, not your confirmation 😉


Ken