调试为什么SKScene init(fileNamed :)返回nil

时间:2016-03-31 11:10:16

标签: ios xcode swift sprite-kit on-demand-resources

TLTR:

问题: SKScene子类init(fileNamed:)返回nil

原因:第二次初始化调用时.sks文件不存在。该问题以某种方式与ODR实现AND / OR行为有关。

说明

使用SpriteKit构建的游戏。我的SKScene子类的init(fileNamed:)返回nil。我想了解“为什么?”如何?”调试此问题。

我的初始化SKScene子类的代码:

/// the hierarchy: SKScene -> TBTBaseScene -> TBTLevelScene

let sceneType: TBTBaseScene.Type = TBTLevelScene.self
let fileName = "Level1"

let scene = sceneType.init(fileNamed: fileName)

很少有事情需要注意:

  1. 此代码在运行时期间的某个时刻起作用,但在另一个时间点起作用。
  2. 当通过Xcode构建目标时,转到产品 - > AppName.app,右键单击“在Finder中显示”,没有Level1.sks。也许没关系,因为应用使用ODRLevel1.sks标有“Level1”标记,即使它位于初始安装标记
  3. 当断点设置为let sceneType:...行时,我可以通过各自的子类和fileNames轻松创建其他游戏场景,但expression TBTLevelScene(fileName:"Level1")会返回nil
  4. 我试图检查主捆绑中是否有Level1.sks,但是对于所有场景,ALWAYS下面的代码都说“FILE NOT AVAILABLE”,所以这种方法似乎是错误的。
  5. 游戏的场景加载架构由DemoBots Sample Code驱动。您可以在LoadSceneOperation.swift中看到类似的方法。但是,那里的初始化在所有情况下都能正常工作。
  6. 基于this answer,我用来检查“Level1”或“Level1.sks”的代码:

    let path = NSBundle.mainBundle().bundlePath
    let url = NSURL(fileURLWithPath: path)
    let filePath = url.URLByAppendingPathComponent(fileName).absoluteString
    let fileManager = NSFileManager.defaultManager()
    if fileManager.fileExistsAtPath(filePath) {
        print("FILE AVAILABLE")
    } else {
        print("FILE NOT AVAILABLE")
    }
    

    更新:

    检查Michael Dautermann提供的文件的方法确实有效,并证明了原因:Level1.sks在第二次尝试加载时遇到

    项目中的Level1.sks文件被添加到“复制包资源”区域,并具有“Level1”ODR标记。该标记位于初始安装标记预取组中。

    在ORD实现中肯定存在一些错误,它在不需要时处理资源(Level1.sks)并且在需要时不再加载它。我会继续努力弄明白。 (似乎,SO社区到目前为止没有任何关系)

1 个答案:

答案 0 :(得分:5)

这里有一些事情正在发生,但最终发生的事情是,它听起来像是你的" Level1"文件不会在构建的应用程序中结束。

1)

您的文件存在检查代码有混合文件URL和文件路径太多。将代码更改为如下所示:

// if nodePath is nil, then it's not found in the bundle
if let nodePath = NSBundle.mainBundle().pathForResource("Level1", ofType: "sks")
{
    print("FILE AVAILABLE")
} else {
    print("FILE NOT AVAILABLE")
}

2)

确保将.sks文件复制到您构建的应用中。

打开你的目标"构建阶段"部分和click on the "Copy Bundle Resources" area。确保您的.sks文件包含在其中。