Reputation: 925
I can't figure out why I am getting this error on the last line: 'SKNode!' is not a subtype of 'SKNode'
func move_background(){
let enumerationBlock: (SKNode, CMutablePointer<ObjCBool>) -> Void = { bg, stop in
var bg_velocity = CGPointMake(0,CGFloat(-self.bg_velocity))
var distance_to_move = self.point_multiply_scalar(bg_velocity, b: self.dt!)
bg.position = self.point_add(bg.position, b: distance_to_move)
if bg.position.y <= -bg.frame.height {
bg.position = CGPointMake(bg.position.x, bg.position.y + bg.frame.height * 2)
}
}
self.enumerateChildNodesWithName("bg", usingBlock: enumerationBlock)
}
Can any of you help me out?
Upvotes: 3
Views: 1300
Reputation: 9464
In the SKNode class, the block argument to this message is of the type (void (^)(SKNode *node, BOOL *stop))
When Swift imports an Objective-C class, all of its message arguments and return values are imported as optionals -- arguments you pass to functions are always NSString?
or NDSData?
, not just NSString
or NSData
. They do this because all pointers in Obj-C can be nil, but a var
in Swift can't be nil unless it has a question mark at the end, thus making it an "optional" type.
So when you define your enmuerationBlock
, it should be of the type
(SKNode?, CMutablePointer<ObjCBool>) -> Void
When you have a mutable pointer, you dereference it by obtaining an UnsafePointer
thus
var val :CMutablePointer<Bool> = /* get this from somewhere */
val.withUnsafePointer() { (p :UnsafePointer<Bool>) in
p.memory = true /* or whatever */
}
.withUnsafePointer
yields an UnsafePointer<T>
to the block, and UnsafePointer<T>
has a memory property that is assignable.
Annoying: You can't test this in the Playground's REPL, it always fails, but it works when you compile it to a proper target.
Upvotes: 8