Reputation: 1109
How can I use a spritekit archive file, where a SpriteNode is located, and have that SpriteNode instantiated "into" a subclass (using Swift?)
I can find the node using scene.childNodeWithName("mysprite") but I don't know how to make it into an instance of my subclass of SKSpriteNode.
Upvotes: 1
Views: 1264
Reputation: 219
You can use this delegate https://github.com/ice3-software/node-archive-delegate or, for swift implementation, smt like this:
class func unarchiveNodeFromFile(file:String)-> SKNode? {
if let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks") {
var fileData = NSData.dataWithContentsOfFile(path, options: NSDataReadingOptions.DataReadingMappedIfSafe, error: nil)
var archiver = NSKeyedUnarchiver(forReadingWithData: fileData)
archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKNode")
let node = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as SKNode
archiver.finishDecoding()
return node
} else {
return nil
}
}
Upvotes: 1
Reputation: 126127
There's no way to set a custom class for a node in the SpriteKit editor in Xcode 6. (That'd be a great feature request to file with Apple, though.)
However, the sks
files you produce in Xcode are just NSKeyedArchiver
archives, and you can use NSKeyedUnarchiver
options to control how your objects get instantiated at load time. So there's a (limited) option for changing classes at load time — you can see this in the template code when you create a new SpriteKit Game project in Xcode 6.
See the SKNode
extension (or category in the ObjC version) in GameViewController.m
: it uses the NSKeyedUnarchiver
method setClass(_:, forClassName:)
to treat the SKScene
instance in the archive as an instance of the template project's GameScene
class instead. You can extend this pattern to create other custom scene classes from Xcode-created archives.
You'll notice, though, that setClass(_:forClassName:)
works on a class-name basis, so it's of limited use if your archive contains several objects of the same class and you want to decode one of them as a different class than the rest. In that case, you might look into using other unarchiver tricks — for example, replacing an object in the unarchiver(_:didDecodeObject:)
delegate method.
Upvotes: 5