Trying to use GKComponent subclass in SpriteKit editor silently crashes Xcode on save

185 views Asked by At

I am trying to work with GameplayKit and SpriteKit using the scene editor in Xcode. I am new to SpriteKit and also have not used NSSecureEncoding before. Pretty new at swift to be honest.

I have a basic GKComponent subclass with one integer one string property implemented like this.

import Foundation
import GameplayKit

@objc
class BasicComponent: GKComponent {

    @GKInspectable var number: Int = 0
    @GKInspectable var text: String = " "

    struct CoderKeys {
        static let stringKey = "StringKey"
        static let integerKey = "IntegerKey"
    }

    override static var supportsSecureCoding: Bool  {
        return true
    }

    required convenience init?(coder aDecoder: NSCoder) {
        self.init(coder: aDecoder)
        if let num = aDecoder.decodeObject(of: NSNumber.self, forKey: CoderKeys.integerKey) { self.number = num.intValue }
        if let tex = aDecoder.decodeObject(of: NSString.self, forKey: CoderKeys.stringKey) { self.text = tex as String }
    }

    override func encode(with aCoder: NSCoder) {
        super.encode(with: aCoder)
        aCoder.encode(self.number as NSNumber, forKey: CoderKeys.integerKey)
        aCoder.encode(self.text as NSString, forKey: CoderKeys.stringKey)
    }


}

Every time I add this component to a node, Xcode crashes silently when the scene is saved (autosave or on purpose). The backtrace in the Xcode crash log file shows an NSInvalidArgumentException:

UNCAUGHT EXCEPTION (NSInvalidArgumentException): *** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[3]
UserInfo: (null)
Hints:

Backtrace:
0   __exceptionPreprocess (in CoreFoundation)
1   DVTFailureHintExceptionPreprocessor (in DVTFoundation)
2   objc_exception_throw (in libobjc.A.dylib)
3   -[CFPrefsConfigurationFileSource initWithConfigurationPropertyList:containingPreferences:] (in CoreFoundation)
4   -[__NSPlaceholderArray initWithObjects:count:] (in CoreFoundation)
5   +[NSArray arrayWithObjects:count:] (in CoreFoundation)
6   -[GTFSceneCustomComponentProperty initWithCoder:] (in GameToolsFoundation)
7   _decodeObjectBinary (in Foundation)
8   -[NSKeyedUnarchiver _decodeArrayOfObjectsForKey:] (in Foundation)
9   -[NSDictionary(NSDictionary) initWithCoder:] (in Foundation)
10   _decodeObjectBinary (in Foundation)
11   _decodeObject (in Foundation)
12   -[NSKeyedUnarchiver decodeObjectForKey:] (in Foundation)
13   -[NSKeyedUnarchiver decodeObjectOfClasses:forKey:] (in Foundation)
14   -[GTFSceneCustomComponent initWithCoder:] (in GameToolsFoundation)
15   _decodeObjectBinary (in Foundation)
16   -[NSKeyedUnarchiver _decodeArrayOfObjectsForKey:] (in Foundation)
17   -[NSArray(NSArray) initWithCoder:] (in Foundation)
18   _decodeObjectBinary (in Foundation)
19   _decodeObject (in Foundation)
20   -[NSKeyedUnarchiver decodeObjectForKey:] (in Foundation)

Also new at reading backtraces but it seems to me that the init?(coder:) fails and returns a null object, which is causing the error.

Furthermore, if i remove the String property, this works flawlessly. I don't know what is causing the init? to fail...

Anyway I could be way off base but I'm quite sure I am missing something simple and will look stupid, but I just can't figure it out.

Thanks for any help.

1

There are 1 answers

1
yesleon On

Use NSString instead of String.