TLTR:
Issue: SKScene
subclass's init(fileNamed:)
returns nil
Reason: The .sks
file does not exist at the time of second initialisation call. The issue somehow related to ODR implementation AND/OR behaviour.
DESCRIPTION:
A game built with SpriteKit
. My SKScene
subclass's init(fileNamed:)
returns nil
. I am trying to understand "why?" and "how?" to debug this issue.
My code for initialising SKScene
subclass:
/// the hierarchy: SKScene -> TBTBaseScene -> TBTLevelScene
let sceneType: TBTBaseScene.Type = TBTLevelScene.self
let fileName = "Level1"
let scene = sceneType.init(fileNamed: fileName)
Few things to note:
Level1.sks
. Perhaps it is OK, because the app uses ODR and Level1.sks
is marked with "Level1" tag, even though it is in Initial Install Tagslet sceneType:...
line, I could easily create other game scenes via respective subclasses and fileNames, but expression TBTLevelScene(fileName:"Level1")
returns nil
.Level1.sks
in the main bundle, but the code below ALWAYS says "FILE NOT AVAILABLE", for all scenes, so the approach seems to be wrong.LoadSceneOperation.swift
. The initialisation there, though, works fine in all cases.The code I use to check the "Level1" or "Level1.sks" exist, based on 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")
}
UPDATE:
Approach for checking files provided by Michael Dautermann does work and it proofs the reason: The Level1.sks
does not exist during second attempt to load it.
The Level1.sks
file in the project is added to "Copy Bundle Resources" area and has "Level1" ODR tag. The tag is in Initial Install Tags prefetched group.
There is definitely some bug in ORD implementation which disposes the resource (Level1.sks
) when it is not needed and does not load it back again at the time it is required. I will keep moving to figure it out. (Seems like, SO community has nothing to do with that so far)
A few things are going on here, but ultimately what's happening is that it sounds like your "Level1
" file isn't ending up in the built application.
1)
Your file existence checking code up there is mixing file URL's and file paths too much. Change your code to look like this:
// 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)
Make sure your .sks file is being copied into your built app.
Open your target's "Build Phases" section and click on the "Copy Bundle Resources" area. Make sure your .sks file is included in there.