Ralph Schipper
Ralph Schipper

Reputation: 741

Xcode Swift how do I print a value form my custom plist file?

Ok I have read so much about NSArray NSDictionary I'm lost now, what I want is to print the value 'name' from the first array item of my custom plist.

This is my plist:

enter image description here

and this is my code in my ViewController.swift:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let path = Bundle.main.path(forResource: "test", ofType: "plist")
        let dic = NSArray(contentsOfFile: path!)
        print(dic?.firstObject)
    }
}

in my console I see:

Optional({
    active = 0;
    name = "John Doe";
})

I would think that print(dic?.firstObject["name"]) would do the trick but I get an error: Value of type 'Any?' has no subscripts

So how do I print the values of name and active of my first array?

I know there are lots of answers on SO regarding this question, that's the reason I got so far. but I just don't know how to fix this.

Kind regards,

Ralph

Upvotes: 0

Views: 983

Answers (2)

vadian
vadian

Reputation: 285092

First of all please never use the NSArray/NSDictionary related API in Swift to read a property list. You are throwing away the type information.

However you can read the values with

let array = NSArray(contentsOfFile: path!) as! [[String:Any]]
for item in array {
    let name = item["name"] as! String
    let active = item["active"] as! Bool
    print(name, active)
}

The dedicated and recommended API is PropertyListSerialization :

let url = Bundle.main.url(forResource: "test", withExtension: "plist")!
let data = try! Data(contentsOf: url)
let array = try! PropertyListSerialization.propertyList(from: data, format: nil) as! [[String:Any]]

A better way is the Codable protocol and PropertyListDecoder

struct User : Decodable {
    let name : String
    let active : Bool
}


override func viewDidLoad() {
    super.viewDidLoad()
    
    let url = Bundle.main.url(forResource: "test", withExtension: "plist")!
    let data = try! Data(contentsOf: url)
    let array = try! PropertyListDecoder().decode([User].self, from: data)
    for item in array {
       print(item.name, item.active)
    } 
}

The code must not crash. If it does you made a design mistake

Upvotes: 4

Gary M
Gary M

Reputation: 438

To use subscripts you first need to cast the object returned by

dic?firstObject

to a dictionary, you can also unwrap the optional at this point.

if let item = dic?firstObject as? [String: Any] {
   print(item["name")
}

Upvotes: 0

Related Questions