首页 > 解决方案 > SpriteKit/GameplayKit 的 Xcode 12.5 NSCoding 问题

问题描述

我正在使用 SpriteKit 开发应用程序,并且在特定对象(GKComponent 对象)上使用 NSCoding 时遇到问题。我在构建设置中使用 Swift 4.0 和 iOS 11。应用程序总是在我试图解码对象的那一行(标有//***)上崩溃。我一直在使用相同的结构来编码/解码其他对象,它们似乎工作正常。不知道为什么它不能与这个特定的 GKComponent 对象一起工作。我花了几个小时试图解决这个问题,但不知道为什么。任何帮助将不胜感激。

提前致谢!

  class ItemEntity: GKEntity {
      
      var name: String!
      var embeddedSpell: KnockbackComponent?

      //Other variables
       
      init(itemName: String) {
            super.init()
            name = itemName
            embeddedSpell = KnockbackComponent(anItem: self)
            addComponent(embeddedSpell!)
           
            //Other initializations
       }

       override func encode(with aCoder: NSCoder) {
           aCoder.encode(self.name, forKey: "Item.name")
           aCoder.encode(embeddedSpell, forKey: "Item.embeddedSpell")
           super.encode(with: aCoder)
       }
 
       required convenience init?(coder aDecoder: NSCoder) {

           let itemName = aDecoder.decodeObject(forKey: "Item.name") as! String        
           self.init(itemName: itemName)

           embeddedSpell = aDecoder.decodeObject(forKey: "Item.embeddedSpell") as? KnockbackComponent
           if embeddedSpell != nil {
              addComponent(self.embeddedSpell!)
           }
       }

      //Other codes
 }

其他类

class KnockbackComponent: GKComponent {
        weak var item: ItemEntity!
        
        init(anItem: ItemEntity) {
            item = anItem
            super.init()
        }
        
        override func encode(with aCoder: NSCoder) {
        
            aCoder.encode(item, forKey: "KnockbackComponent.item")
            super.encode(with: aCoder)
        }
        
        required convenience init?(coder aDecoder: NSCoder) {
            //***This line causes crash with error msg Thread 1: EXC_BAD_INSTRUCTION***//
            let item = aDecoder.decodeObject(forKey: "KnockbackComponent.item") as? ItemEntity //<--error msg Thread 1: EXC_BAD_INSTRUCTION
            self.init(anItem: item!)
        }
        
        
        //Other codes
        
  }

标签: sprite-kitswift4nscodinggameplay-kit

解决方案


我通过使用以下代码让我的 GKComponent 类符合 Codable 解决了这个问题:

override func encode(to encoder: Encoder)  {
        
    var container = encoder.container(keyedBy: CodingKeys.self)
    try? (container.encode(itemEnt, forKey: .itemEnt))
         
}
    
    
required convenience init(from decoder: Decoder) throws {
        
    let container = try decoder.container(keyedBy: CodingKeys.self)
       
    let itemEntity = try container.decode(ItemEntity.self, forKey: .itemEnt)
        self.init(entity: itemEntity)
}

推荐阅读