调试为啥 SKScene init(fileNamed:) 返回 nil
Posted
技术标签:
【中文标题】调试为啥 SKScene init(fileNamed:) 返回 nil【英文标题】:Debug why SKScene init(fileNamed:) returns nil调试为什么 SKScene init(fileNamed:) 返回 nil 【发布时间】:2016-03-31 11:10:15 【问题描述】:TLTR:
问题: SKScene
子类的init(fileNamed:)
returns 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)
注意事项:
-
此代码在运行时的某个时间点起作用,但在其他时间点不起作用。
当通过Xcode构建目标时,转到Products -> AppName.app,右键单击“Show in Finder”,没有
Level1.sks
。也许没关系,因为应用程序使用了ODR,而Level1.sks
标记有“Level1”标签,即使它在初始安装标签中
当断点设置为let sceneType:...
行时,我可以通过相应的子类和文件名轻松创建其他游戏场景,但expression TBTLevelScene(fileName:"Level1")
返回nil
。
我尝试检查主包中是否有 Level1.sks
,但对于所有场景,下面的代码总是显示“文件不可用”,因此该方法似乎是错误的。
游戏的场景加载架构由DemoBots Sample Code 驱动。您可以在LoadSceneOperation.swift
中看到类似的方法。不过,那里的初始化在所有情况下都可以正常工作。
我用来检查“Level1”或“Level1.sks”的代码是否存在,基于this answer:
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 社区与此无关)
【问题讨论】:
【参考方案1】:这里发生了一些事情,但最终发生的事情是,听起来您的“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 文件包含在其中。
【讨论】:
检查文件存在的方法确实有效。它显示“Level1.sks”在应用程序崩溃时不可用。但是,“复制捆绑资源”区域确实有“Level1.sks”。 文件没有复制到构建的应用程序中一定有某种原因。构建日志有什么有用的吗? (使用“显示所有消息”) 请看我的更新。您的代码被剪断有助于缩小案件范围。谢谢。 @Michael Dautermann 我将您的答案标记为“已接受”,因为它帮助我找出了 init 返回nil
的关键原因。问题“为什么在第二次通话期间丢失了文件?”是另一种故事,可能是完全不同的问题。感谢您的帮助!以上是关于调试为啥 SKScene init(fileNamed:) 返回 nil的主要内容,如果未能解决你的问题,请参考以下文章
我应该在 init 方法中还是在 didMove(toView:) 中以编程方式设置 SKScene?
为啥 SKSpriteNode(fileNamed:) 使用 Swift 在 iOS 中生成 nil?