Categories
ios nsdictionary plist swift uitableview

Swift Plist Reading and Initializing Arrays as Objects for Key

I’m developing a small UITableView-based app in Swift. I started out hard-coding some basic arrays as such (included is the basic class declaration and the UITableView outlet declaration:

import UIKit
class ScenesViewController: UITableViewController {
@IBOutlet var myTableView: UITableView
var sceneName = ["Scene 1", "Scene 2", "Scene 3", "Scene 4", "Scene 5"]
var sceneDetail = ["Hi", "Hello", "Bye", "My Bad", "Happy"]

This code is inside a UITableViewController which has an outlet that is all hooked up to a UITableView. I have created a plist for this called “Scenes.plist” and have attempted to replace the code. In Objective-C, I would do this:

NSString *path = [[NSBundle mainBundle] pathForResource:@"Scenes" ofType:@"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
sceneName = [dict objectForKey:@"SceneName"];
sceneDetail = [dict objectForKey:@"SceneDetail"];

I started doing this in Swift like this:

let path = NSBundle.mainBundle().pathForResource("Scenes", ofType:"plist")
let dict = NSDictionary(contentsOfFile:path) // Error: 'ScenesViewController.Type' does not have a member named 'path'

I scoured the Internet for a solution but was unable to find one. So I took up the next course of action – an ‘almost’ one-liner:

let dict = NSDictionary(contentsOfFile: 
NSBundle.mainBundle().pathForResource("Scenes", ofType:"plist"))
var sceneName = dict["SceneName"] // Error: 'ScenesViewController.Type' does not have a member named 'dict'

Now, the only solution I can almost resort to is having all of that on one line for each array:

var sceneName = NSDictionary(contentsOfFile: 
NSBundle.mainBundle().pathForResource("Scenes", ofType:"plist").objectForKey("SceneName")
// Warning: Variable 'sceneName' inferred to have type 'AnyObject!', which may be unexpected
// Fix-It: Add an explicit type annotation to silence this warning (var sceneName: AnyObject! = ...)

So I added the explicit type annotation just to find out that there were more errors. Inside the cellForRowAtIndexPath: function:

override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell? {
let cell: UITableViewCell = tableView!.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) as UITableViewCell
// Configure the cell...
cell.textLabel.text = sceneName[indexPath!.row] // Error: could not find member 'row'
return cell
}

There are actually two errors; I do not know whether this is accidentally duplicated or not. The next error(s) are in the the prepareForSegue:sender: method:

override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) {
if segue?.identifier == "ShowDetails" {
var detailVC: ScenesDetailViewController = segue!.destinationViewController as ScenesDetailViewController
var myIndexPath: NSIndexPath = myTableView.indexPathForSelectedRow()
var row: Int = myIndexPath.row
detailVC.detailModal = [sceneDetail[row], sceneName[row]] // Error: Could not find an overload for 'subscript' that accepts the supplied arguments
}
}

Again, there are two errors; however, I believe this is because sceneDetail and sceneName are both used. There seem to be errors all over the place with reading and using plists in files that aren’t there (or that I haven’t come across) in Objective-C.