【问题标题】:Access a plist in Swift (error: "Expressions are not allowed at the top level")在 Swift 中访问一个 plist(错误:“表达式不允许在顶层”)
【发布时间】:2014-06-20 20:26:02
【问题描述】:

我有一个 plist,我想在 Xcode 中以 Swift 字典的形式访问它。我可以将文件的内容定义为 NSDictionary 但每次我尝试从中访问特定的值/对象时,它都会显示错误“表达式不允许在顶层”。我已经使用自动完成尝试了括号表示法、类型转换和类方法(使用点表示法)。

我的 plist 包含字典,其中包含的字典包含带有 CGFloats 和字符串的字典。

我想访问实例的值。

这是我用来定义它的代码,它位于我的 GameScene.swift 的开头(它是一个 SpriteKit 游戏):

let levelBlocks = NSDictionary(contentsOfFile: NSBundle.mainBundle().pathForResource("LevelBlocks", ofType: "plist"))

我希望能够做到:

levelBlocks["Level1"]

编辑:添加了更多信息。

我还尝试将它放在 ViewDidLoad()、init() 中,并在函数内部使用符合 Hashable 的泛型而不是 AnyObject/Any。我仍然无法访问字符串。

编辑 2:我在 ViewDidLoad() 中尝试过这个,它返回错误 254:

let levelBlocks = NSDictionary(contentsOfFile: NSBundle.mainBundle().pathForResource("LevelBlocks", ofType: "plist")) as Dictionary<String, Dictionary<String, Dictionary<String, String>>>
let test = levelBlocks["Level1"] as Dictionary<String, Dictionary<String, String>>
let test1 = test["Block0"] as Dictionary<String, String>
let test2 = test1["color"] as String
println(test2)

【问题讨论】:

  • 我们能看到更多周围的环境吗?也许这个代码嵌套的类?

标签: ios xcode swift ios8


【解决方案1】:

这是我找到的解决方案:

let levelBlocks = NSDictionary(contentsOfFile: NSBundle.mainBundle().pathForResource("LevelBlocks", ofType: "plist"))
let test: AnyObject = levelBlocks.objectForKey("Level1")
println(test) // Prints the value of test

我将test 的类型设置为AnyObject,以使有关可能发生的意外推断的警告静音。

此外,它必须在类方法中完成。

访问和保存已知类型的特定值:

let value = levelBlocks.objectForKey("Level1").objectForKey("amount") as Int
println(toString(value)) // Converts value to String and prints it

【讨论】:

    【解决方案2】:

    当您在类或实例方法之外有表达式时,Xcode 会给出该错误。声明像levelBlocks 这样的全局变量是可以的,但是尝试调用变量上的方法(这是下标所做的)是一个表达式,并且不允许在那里。如果您只是测试一下,您可以创建另一个全局:

    let levelBlocks = NSDictionary(contentsOfFile: NSBundle.mainBundle().pathForResource("LevelBlocks", ofType: "plist"))
    let level1 = levelBlocks["level1"]
    

    但实际上任何类型的操作都应该发生在你的类中。

    注意:这适用于“.swift”文件——playgrounds 就是为这种非正式的实验而构建的。您尝试的代码在操场上是否有效?


    这是一个 Swift 文件的细分,其中包含一个具有不同级别范围的类,如 cmets 所示:

    // MyViewController.swift
    
    let globalNumber = 10           // global scope: can be accessed from 
                                    // anywhere in this module.
    
    class MyViewController : ViewController {
        var instanceNumber = 5      // instance scope: instances of this class each
                                    // maintain their own value. should be
                                    // accessed within methods using self.varname
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            var localNumber = self.instanceNumber * globalNumber
                                    // local scope: will disappear after this method
                                    // finishes executing (in most cases)
        }
    }
    

    在您的情况下,您需要加载 plist 并在您的一个类中访问其值,可能是 init...DidLoad 方法。

    至于从字典中提取项目,请记住 NSDictionary 作为 Dictionary 直接桥接到 Swift,因此您可以像这样加载和解析它:

    let path = NSBundle.mainBundle().pathForResource("LevelBlocks", ofType: "plist")
    if let levelBlocks = NSDictionary(contentsOfFile: path) as? Dictionary<String, AnyObject> {
        let level1 = levelBlocks["level1"]                    // level1 is of type AnyObject?
        let level2 = levelBlocks["level2"] as NSString        // type NSString
        let level3: String = levelBlocks["level3"] as NSString     // type String
    }
    

    【讨论】:

    • 不,它在名为 GameScene.swift 的文件中使用。
    • 当我尝试在继承自 SKScene 并实现 SKPhysicsContactDelegate 协议的 GameScene 类中执行此操作时,我收到错误“'GameScene.Type' 没有名为 'levelBlocks' 的成员”,即使两个对象都被声明为变量并且它们没有在类之外声明。
    • 使用您的代码,我遇到了建议 let level1: AnyObject! = levelBlocks["level1"] 的问题。当我输入let level1: NSDictionary = levelBlocks["level1"] 时,它建议let level1: NSDictionary = levelBlocks["level1"] as NSDictionary。有没有办法将其转换为 Swift 字典?
    • 第二行需要在实例 method 中发生 - 您不能声明具有基于另一个属性的值的属性。我添加了一些说明。
    • 感谢您的回复。它不适用于 AnyObject,但除了最后一行之外的所有代码都可以在我的 EDIT 2 中使用。最后一行应该可以工作,因为test2 是一个字符串,println() 接受一个字符串。这些类型对应于我的 plist 中的类型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 1970-01-01
    • 1970-01-01
    • 2014-08-29
    • 1970-01-01
    相关资源
    最近更新 更多