Kwangle Kwangle - 1 month ago 10
Swift Question

Swift unable to locate and read property list (.plist) file

I'm having a real problem in getting a simple command line OSX Swift program to read data from a simple .plist XML file - in fact the program can't even see the file despite it seemingly being present and copied into the bundle.

The data is handled by a class that is meant to read and copy the plist data into an array where it can be retrieved without the plist needing to be queried again:

// Datadump.swift

import Foundation

class Datadump {

//array of dictionaries containing string keys and any datatype of value
var dataArray : Array<Dictionary<String,AnyObject>>

init () {
//copies data from plist
let bundle = NSBundle.mainBundle()
let path = bundle.pathForResource("Hardware", ofType: "plist")
//check file located
print("File Location: \(path) " )
let productArray = NSArray(contentsOfFile: path!)

dataArray = productArray as! Array<Dictionary<String,AnyObject>>
}

//returns tuple based on product id
func getData(prodId: Int) -> (String, Int) {

//returned vars
var price = 0
var name : String = ""

//iterate through array until relevant product is found
for dict in dataArray{
if dict["ProdId"] as! Int == prodId{
price = dict["Price"] as! Int
name = dict["Name"] as! String
break
}
}
return (name, price);
}

}


However the program fails with a fatal error as soon as the:

let productArray = NSArray(contentsOfFile: path!)


line is reached, with the output:

File Location: nil fatal error: unexpectedly found nil while unwrapping an Optional value

The print statement confirms that the program cannot find the Hardware.plist file.

The main program just creates and instance of the class and runs a function but obviously fails as soon as the init () of the class runs as mentioned above:

// main.swift

import Foundation

//creates instance of Datadump class
var myData = Datadump ()

//queries data, copies result to tuple
let (nam, pri) = myData.getData(123)
print ("Name: \(nam) Price: \(pri)")


The Hardware.plist file looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>Name</key>
<string>Intel i7 CPU</string>
<key>Price</key>
<integer>13995</integer>
<key>ProdId</key>
<integer>123</integer>
</dict>
<dict>
<key>Name</key>
<string>19&quot; Monitor</string>
<key>Price</key>
<integer>9995</integer>
<key>ProdId</key>
<integer>456</integer>
</dict>
<dict>
<key>Name</key>
<string>8GB DDR Ram</string>
<key>Price</key>
<integer>4595</integer>
<key>ProdId</key>
<integer>789</integer>
</dict>
</array>
</plist>


I've tried everything I can think of including looking at the settings for the .plist file and reimporting it in different ways.

Any help would be greatly appreciated!

Many thanks,
Kwangle

Answer

Normally, this is what you do:

In the Project Navigator (on the left), select the plist file. In the File Inspector (on the right), examine the target membership settings. You will probably find that the app target is not checked. This means that the plist file is not being copied into the app bundle when you build it. Check the app target, and all will be well.

But you can't do that, because this is a command line program. It is an executable and no more. There is no bundle to copy into. What you're trying to do is metaphysically impossible.

Comments