2017-10-13 6 views
0

Je ne peux pas comprendre pourquoi le code ci-dessous ne fonctionne pas:vecteur magasin à NSData à Swift

import Foundation 
import SpriteKit 

var TestVector: CGVector = CGVector(dx: 1, dy: 1) 

var Data: Dictionary<String, Any> = ["abc":CGPoint(x: 0, y: 0), "def":1, "ghi":"Try", "jkl":TestVector] 


let DataConverted: Data = NSKeyedArchiver.archivedData(withRootObject: Data) 

let DataReceived: Dictionary = (NSKeyedUnarchiver.unarchiveObject(with: DataConverted) as! [String : Any]) 

Erreur lance est: Erreur: exécution a été interrompue, la raison: le signal SIGABRT. Le processus a été laissé à l'endroit où il a été interrompu, utilisez "thread return -x" pour revenir à l'état avant l'évaluation de l'expression.

Tout fonctionne très bien pour beaucoup de différents types de données (String, Int, Double, ...), mais il ne fonctionne pas pour les vecteurs

limitations sont là dans le type de données qui peuvent être archivés via NSKeyedArchiver?

Thx

J.

Informations complémentaires: ce doit être utilisé dans un transfert de données MultipeerConnectivy

+0

'CGPoint' ne doit pas par défaut ne peut pas être converti en tant que tels dans' (NS) Data', donc il ne peut pas être archivé. Idem pour 'TestVector'. Vous devez le conformer au protocole 'NSCoder'. – Larme

+0

Thx. Il travaille cependant pour CGPoint. Seul le type CGVector renvoie une erreur. Seriez-vous capable de dire comment conformer CGPoint et CGVector au protocole NSCoder et quelle serait la meilleure syntaxe? – jbegood

+2

@Larme Vous voulez dire 'NSCoding' –

Répondre

0

Check out NSValue, il est parfait dans ce scénario.

Ajouter comme NSValue(cgVector: TestVector) et quand vous lisez en arrière du dictionnaire tout simplement le récupérer comme CGVector comme si let vector = cgVectorValue.cgVectorValue

Dans votre cas, vous faites:

var TestVector: CGVector = CGVector(dx: 1, dy: 1) 
let vectorValue = NSValue(cgVector: TestVector) 

let pointValue = NSValue(cgPoint:CGPoint(x: 0, y: 0)) 

var Data: Dictionary<String, Any> = ["abc":pointValue, "def":1, "ghi":"Try", "jkl":vectorValue] 

let DataConverted: Data = NSKeyedArchiver.archivedData(withRootObject: Data) 

let DataReceived: Dictionary = (NSKeyedUnarchiver.unarchiveObject(with: DataConverted) as! [String : Any]) 

if let vectorValue = DataReceived["jkl"] as? NSValue { 
    let vector = vectorValue.cgRectValue 
} 

if let pointValue = DataReceived["abc"] as? NSValue { 
    let point = vectorValue.cgPointValue 
} 

Apple utilise tout le temps, peut-être vous l'avez vu quand vous obtenez une notification pour le clavier montrera, à l'intérieur du dictionnaire userInfo vous pouvez obtenir la taille de clavier en utilisant

CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size 

Notez que le CGRectValue, obtenir CGRect qui a été encapsulé en utilisant NSValue

A partir de docs Apple:

An NSValue object can hold any of the scalar types such as int, float, and char, as well as pointers, structures, and object id references. Use this class to work with such data types in collections (such as NSArray and NSSet), Key-value coding, and other APIs that require Objective-C objects. NSValue objects are always immutable.

Plus sur https://developer.apple.com/documentation/foundation/nsvalue

+0

Thx mais cela ne fonctionne pas. Erreur: Terminaison de l'application en raison d'une exception non interceptée 'NSInvalidArgumentException', raison: '*** - [NSKeyedArchiver encodeValueOfObjCType: at:]: cet archiveur ne peut pas coder' Sur la ligne "laissez DataConverted ..." – jbegood

+0

J'ai mis à jour la réponse , vous avez également eu un CGPoint là, vous enveloppez cela dans NSValue ainsi que vous pouvez voir ci-dessus et puis il doit fonctionner – Ladislav

+0

Je serais d'accord avec d'autres qui ont commenté sur la création d'une classe personnalisée qui se conforme au protocole NSCoding ... – Ladislav