3

TLTR:

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

原因:第二.sks次初始化调用时文件不存在。该问题在某种程度上与ODR实施和/或行为有关。

描述:

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 构建目标时,转到 Products -> AppName.app,右键单击“Show in Finder”,没有Level1.sks。也许没关系,因为应用程序使用ODRLevel1.sks标有“Level1”标签,即使它位于初始安装标签中
  3. 当断点设置为let sceneType:...line 时,我可以通过相应的子类和文件名轻松创建其他游戏场景,但expression TBTLevelScene(fileName:"Level1")返回nil.
  4. 我试图检查Level1.sks主捆绑包中是否存在,但对于所有场景,下面的代码总是说“文件不可用”,所以这种方法似乎是错误的。
  5. 游戏的场景加载架构由DemoBots 示例代码驱动。您可以在 中看到类似的方法LoadSceneOperation.swift。但是,那里的初始化在所有情况下都可以正常工作。

基于此答案,我用来检查“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文件被添加到“Copy Bundle Resources”区域并具有“Level1”ODR 标签。该标签位于Initial Install Tags预取组中。

ORD 实现中肯定存在一些错误,它会在不需要时释放资源 ( Level1.sks),并且不会在需要时再次加载它。我会继续努力弄清楚。(似乎到目前为止,SO 社区与此无关)

4

1 回答 1

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 文件被复制到您构建的应用程序中。

打开目标的“构建阶段”部分,然后单击“复制捆绑资源”区域。确保您的 .sks 文件包含在其中。

于 2016-03-31T11:25:24.130 回答