Search code examples
swiftsprite-kitsetvalue

How to Create a Value for key


Im trying to have my SKNode have a value forkey that I can access to get a value from. Its just like the name property (skspritenode.name) but I want to be able to have booleans be the value.

This is how I'm trying to create this value.

block.setValue(false, forUndefinedKey: "is-Block")

Then when I try to access it I use this

if block.valueForKey("is_Block") == true {
   //run code here
}

I'm stumped. Any suggestions? I apologize if this is a little confusing. I'm not good at explaining simple things.


Solution

  • The issue is that is_Block does not exist on SKNode.

    setValue forUndefinedKey will raise NSUndefinedKeyException by default.

    If you had a subclass, you would override this function to do what you want to do.

    See https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueCoding/Articles/BasicPrinciples.html to better understand key value coding.

    If you want to have SKNode have a custom variable named is_Block, you are going to have to create an extension for SKNode, and create a property that will store this data for you.

    import Foundation
    import SpriteKit
    import ObjectiveC
    
    extension SKNode{
        var isBlock: Bool {
            get {
                var key = "isBlock";
    
                guard let block = objc_getAssociatedObject(self, &key) as? Bool
                else{
                    print("Error");
                    return false
                }
                print("Success");
                return block
            }
            set(newValue) {
                var key = "isBlock";
                print("Setting \(newValue)")
                objc_setAssociatedObject(self, &key, newValue , objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
            }
        }
    
    }
    

    Test in playground:

    import Foundation
    import SpriteKit
    import ObjectiveC
    
    extension SKNode{
        var isBlock: Bool {
            get {
                var key = "isBlock";
    
                guard let block = objc_getAssociatedObject(self, &key) as? Bool
                else{
                    print("Error");
                    return false
                }
                print("Success");
                return block
            }
            set(newValue) {
                var key = "isBlock";
                print("Setting \(newValue)")
                objc_setAssociatedObject(self, &key, newValue , objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
            }
        }
    
    }
    
    
    let a = SKNode()
    let b = SKNode()
    
    a.isBlock = false
    b.isBlock = true
    print ("\(a.isBlock), \(b.isBlock)")    
    
    b.isBlock = false
    a.isBlock = true
    print ("\(b.isBlock), \(a.isBlock)")