iosuitableviewnsdictionaryplistswift

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'

Next option:

let dict = NSDictionary(contentsOfFile: 
    NSBundle.mainBundle().pathForResource("Scenes", ofType:"plist"))

var sceneName = dict["SceneName"] // Error: 'ScenesViewController.Type' does not have a member named 'dict'

Finally:

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.


Solution

  • To resolve your initial problem, put the code inside a func, like:

    var memoryName = []
    var memoryDetail = []
    
    override func awakeFromNib() {
        super.awakeFromNib()
    
        let path = NSBundle.mainBundle().pathForResource("Memories", ofType:"plist")
        let dict = NSDictionary(contentsOfFile:path)
    
        memoryName = dict["MemoryName"] as Array<String>
        memoryDetail = dict["MemoryDetail"] as Array<String>
    }