Dan Hixon
Dan Hixon

Reputation: 925

'SKNode!' is not a subtype of 'SKNode'

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

Answers (1)

iluvcapra
iluvcapra

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

EDIT answering flainez's question below:

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

Related Questions