2016-12-06 2 views
1

J'ai fait des recherches sur interweb, en particulier sur Stack overflow, et sur mes propres références à la maison, mais je n'ai pas été capable de comprendre ce qui ne va pas avec mon code. J'ai passé la plus grande partie de la journée à essayer de comprendre ce problème, et j'espère que quelqu'un ici pourra m'aider dans la bonne direction.convertir un objet personnalisé en NSData Swift

Configuration:
J'ai une application d'échecs que je construis à Swift 3.0, et la structure est la suivante: BoardModel est la classe qui contient toutes les données sur le jeu, Piece est une classe au sein du conseil modèle qui contient des données sur lui-même dans le BoardModel, Piece a également un enum PieceType pour .knight, .king, etc.

Le BoardModel a un tableau 2D de pièce représentant l'échiquier. Maintenant, à chaque mouvement, je veux enregistrer les données du jeu dans Game Center, mais avant même que je puisse essayer de stocker les données du jeu, l'encodage jette une erreur et c'est là que je suis. L'erreur pointe juste sur AppDelegate avec l'instruction: "Thread: 1 signal SIGABRT".

Voici le code qui est le problème avec la classe Piece:

let pieceData = NSKeyedArchiver.archivedData(withRootObject: board.board[0][0]) // where the error is thrown 

class Piece: NSObject, NSCoding { 
    var isSelected: Bool 
    var type: PieceType 
    var isWhite: Bool 
    var isFirstMove: Bool 
    var symbol: String! 
    var position: (row: Int, col: Int)! 

    override init() { 
     isSelected = false 
     type = PieceType.empty 
     isWhite = true 
     isFirstMove = true 
    } 

    required init(coder aDecoder: NSCoder) { 
     isSelected = aDecoder.decodeBool(forKey: "isSelected") 
     type = aDecoder.decodeObject(forKey: "type") as! BoardModel.PieceType 
     isWhite = aDecoder.decodeBool(forKey: "isWhite") 
     isFirstMove = aDecoder.decodeBool(forKey: "isFirstMove") 
     symbol = aDecoder.decodeObject(forKey: "symbol") as! String 
     position = aDecoder.decodeObject(forKey: "position") as! (Int, Int) 
    } 

    func encode(with aCoder: NSCoder) { 
     aCoder.encode(isSelected, forKey: "isSelected") 
     aCoder.encode(type, forKey: "type") 
     aCoder.encode(isWhite, forKey: "isWhite") 
     aCoder.encode(isFirstMove, forKey: "isFirstMove") 
     aCoder.encode(symbol, forKey: "symbol") 
     aCoder.encode(position, forKey: "position") 
    } 

    init(isSelected: Bool, type: PieceType, isWhite: Bool, isFirstMove: Bool, symbol: String, position: (Int, Int)) { 
     self.isSelected = isSelected 
     self.type = type 
     self.isWhite = isWhite 
     self.isFirstMove = isFirstMove 
     self.symbol = symbol 
     self.position = position 
    } 

    func setPosition(to newPosition: (row: Int, col: Int)) { 
     position = newPosition 
    } 
} 
+0

ce qui est PieceType? est Enum ou objet personnalisé (NSObject)? –

+0

@jigneshVadadoriya le PieceType est enum –

+0

Avez-vous fourni un NSCoder pour le type de données de position? Essayez de commenter la position de votre code et voyez si vous vous plantez toujours. Vous devrez probablement fournir un NSCoder pour le PieceType en fonction de la façon dont vous l'avez implémenté. – jvarela

Répondre

1

si votre Enum est comme ce PieceType et le type est Int

enum PieceType : Int { 
    case empty 
    case notEmpty 

} 

écrire ensuite encode et decode méthode comme de cette façon

required init(coder aDecoder: NSCoder) { 
     isSelected = aDecoder.decodeBool(forKey: "isSelected") 
     type = PieceType(rawValue: aDecoder.decodeObject(forKey: "type") as! Int)! 
     isWhite = aDecoder.decodeBool(forKey: "isWhite") 
     isFirstMove = aDecoder.decodeBool(forKey: "isFirstMove") 
     symbol = aDecoder.decodeObject(forKey: "symbol") as! String 
     position = aDecoder.decodeObject(forKey: "position") as! (Int, Int) 
    } 

    func encode(with aCoder: NSCoder) { 
     aCoder.encode(isSelected, forKey: "isSelected") 
     aCoder.encode(type.rawValue, forKey: "type") 
     aCoder.encode(isWhite, forKey: "isWhite") 
     aCoder.encode(isFirstMove, forKey: "isFirstMove") 
     aCoder.encode(symbol, forKey: "symbol") 
     aCoder.encode(position.row, forKey: "position.row") 
     aCoder.encode(position.col, forKey: "position.col") 
    } 

i ont vérifier le code ci-dessous et le travail des

let pice = Piece(isSelected: true, type: .empty, isWhite: true, isFirstMove: true, symbol: "Test", position: (2, 10)) 
let pieceData = NSKeyedArchiver.archivedData(withRootObject:pice) 
print(pieceData) 

Et ÉTEINDRE est

386 bytes 
+0

cela fonctionne uniquement avec des pièces vierges comme vous l'avez instancié dans votre exemple. Cela ne fonctionnera pas avec ----------------------- laissez somePiece = BoardModel.Piece (isSelected: false, tapez: BoardModel.PieceType.knight, isWhite: true, isFirstMove: true, symbole: "Wknight", position: (0, 1)) –

+0

J'ai supprimé l'instance de position et cela a fonctionné, mais j'ai besoin de la position, donc je dois me résoudre à faire. @ jvarela, a commenté ma question et a dit de fournir un NSCoder pour la position, mais je ne suis pas sûr de la façon de le faire. jignesh, avez-vous une idée de la meilleure façon de le faire? –

+0

laissez-moi essayer d'une autre manière –