Swift Plist 读取和初始化数组作为键的对象

Posted

技术标签:

【中文标题】Swift Plist 读取和初始化数组作为键的对象【英文标题】:Swift Plist Reading and Initializing Arrays as Objects for Key 【发布时间】:2014-06-13 16:02:12 【问题描述】:

我正在用 Swift 开发一个基于 UITableView 的小型应用程序。我开始对一些基本数组进行硬编码(包括基本类声明和UITableView outlet 声明:

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"]

此代码位于UITableViewController 内,该UITableViewController 有一个连接到UITableView 的插座。我为此创建了一个名为“Scenes.plist”的 plist,并尝试替换代码。在 Objective-C 中,我会这样做:

NSString *path = [[NSBundle mainBundle] pathForResource:@"Scenes" ofType:@"plist"];

NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
sceneName = [dict objectForKey:@"SceneName"];
sceneDetail = [dict objectForKey:@"SceneDetail"];

我开始在 Swift 中这样做:

let path = NSBundle.mainBundle().pathForResource("Scenes", ofType:"plist")

let dict = NSDictionary(contentsOfFile:path)  // Error: 'ScenesViewController.Type' does not have a member named 'path'

我在 Internet 上搜索了解决方案,但找不到解决方案。所以我采取了下一步行动——“几乎”单线:

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

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

现在,我几乎可以求助的唯一解决方案是将所有这些都放在每个数组的一行中:

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! = ...)

所以我添加了显式类型注释只是为了发现还有更多错误。 cellForRowAtIndexPath: 函数内部:

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

实际上有两个错误;我不知道这是否是意外重复的。下一个错误在 prepareForSegue:sender: 方法中:

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
    

同样,有两个错误;但是,我相信这是因为sceneDetailsceneName 都被使用了。在 Objective-C 中不存在(或者我没有遇到过)的文件中读取和使用 plist 似乎到处都是错误。

【问题讨论】:

NSIndexPathrowsection 属性在UIKit 中定义,而不是在Foundation 中定义。将import UIKit 添加到您的文件中是否可以解决此问题? @JackWu UIKit 已经被导入;这是第一行 【参考方案1】:

要解决您最初的问题,请将代码放在 func 中,例如:

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>

【讨论】:

【参考方案2】:

您可以通过将代码移动到对象初始化后调用的函数来解决此问题。

属性作为对象初始化的一部分进行初始化。您已将 path 和 dict 创建为属性,并尝试使用不符合初始化要求的代码对其进行初始化。

初始化器不能调用任何实例方法,请阅读 任何实例属性的值,或将 self 称为值 直到初始化的第一阶段完成。

--Swift 编程语言 - 初始化 - 安全检查 4

此外,您似乎只希望并且需要将 sceneNamesceneDetail 作为属性,因此您可以在用于填充 sceneDetail 的方法范围内完全移动它们以及初始化后的场景名称。

我很难说出下标错误是什么确切,因为我看不到 detailVC.detailModal 应该包含什么类型的数据;即便如此,似乎将错误类型的对象传递到 detailModal 数组中。这个问题的一个很好的小描述是Swift and arrays

【讨论】:

以上是关于Swift Plist 读取和初始化数组作为键的对象的主要内容,如果未能解决你的问题,请参考以下文章

如何在 swift 中读取数组和字典的 plist

Swift 3 - 从 plist 的所有数组中获取所有项目

Swift:如何在 plist 的数组中读取多个数组?

在iOS9 swift中的字典类型中添加数组作为键和值

将数组内容(自定义类型)写入 plist 作为 swift 中的键控数组

Swift 编辑 plist 数组