Comment lire un fichier encodé avec une App mac dans une App iOS
iLandes
Membre
J'ai un problème avec ce code qui provoque l'émission du message : "The class may be defined in source code or a library that is not linked"
if let readingDate = NSKeyedUnarchiver.unarchiveObjectWithData(data) as? [MoonDirection] {
moonDirections = readingDate
}
J'utilise une classe MoonDirection qui vient d'un autre project mais que j'ai mis (sans la copier) dans le projet dont est issu ce code.
La classe est bien reconnu mais il m'est impossible de faire fonctionner le code cité ci-dessus. Bien que le message de la console soit verbeux je ne le comprends pas. Pas mal de recherche sur le net n'ont rien éclairci.
D'avance, merci de votre aide.
Mots clés:
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Si Xcode étais intelligent, cela se saurait ..
Il n'y a pas d'autres infos avec le message d'erreur ?
Merci pour votre intérêt porté à ma requête. Le message complet est :
GardeningByTheMoonViewer[2108:136966] *** Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: '*** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (GardeningByTheMoonEditor.MoonDirection) for key (NS.objects); the class may be defined in source code or a library that is not linked'
*** First throw call stack:
Ca à donc quelque chose à voir avec ma classe (MoonDirection) et NSKeyedUnarchiver. A priori plus avec NSKeyedUnarchiver car je peux utiliser ma classe correctement lorsque je l'initialise normalement...
Tu peux montrer le code de ta classe lunatique ?
Là voilà , rien d'extraordinaire apparement :
Je suis loin d'être un spécialiste en encodage/encodage, mais cela me perturbe de voir que tu encodes un nil sous une clé. Il ne serait pas plus intelligent dans ce cas de ne rien encoder ? Et de tester l'absence ou la présence de la clé au décodage ?
Je suppose que Swift considère que la classe MoonDirection du module GardeningByTheMoonEditor est différente de la classe du module GardeningByTheMoonViewer.
Cette ligne indique NSKeyedUnarchiver d'utiliser la classe de MoonDirection de l'application plutôt que celle donné par le module.
Plus je cherche moins je trouve. J'ai essayé de créer une classe identique directement dans mon projet viewer. J'ai le même message du coup je vais me replonger dans mes livres. Il me semble que dans ce que j'ai étudié ils implémentaient aussi NSCopying.
Je continue mes recherches...
Apparemment tu essaie de charger un objet créer avec la même classe mais depuis une application différente et donc depuis une module différent.
Peut être devrait-tu créer un framework contenant ta classe MoonDirection avec lequel tu pourrais effectuer la (dé)sérialization. Du coup le nom du module serait le même et tu n'aurais plus ce problème.
L'idée du framework me plaisait bien. Je n'en avais créé. Maintenant c'est fait mais cela ne résout pas mon problème. ;D
Ce soir me vient une idée. Je change le titre du post et je me repose la question. Comme quoi Draken, les proverbes ont du bon quand on fait l'effort de les méditer un peu. Avec 4h30 de temps sans prise de courant j'ai eu le temps.
Je repose donc mon problème, je ferais aussi des recherches sur google demain.
Ce que je veux c'est lire des données encodé avec NSCode dans une application Mac (éditeur) et les lire dans une application iOS (viewer).
En attendant si vous avez des pistes je suis preneur...
Recopies le fichier dans ton projet juste pour voir. C'est peut être tout bonnement un problème de path (Xcode est vraiment très très con des fois).
Pour moi c'est clairement un problème de scope (surtout vu le message et le fait que tu utilises Swift où les namespaces sont implicites).
Si tu as créer un framework contenant la classe MoonDirection il faut exclusivement utiliser la classe du framework dans les deux applications. Tu peux même ajouter le nom du module lors de la création d'instance pour être certain d'utiliser la bonne classe et tu peux vérifier le nom de la classe utilisé en lisant le fichier sauvegardé avec un simple éditeur hexadécimal. (testé sous Xcode 7.3)
As tu testé la méthode setClass de NSKeyedUnarchiver ? c'est surement le moyen le plus rapide pour relire le fichier (mais aussi le plus contraignant).
Tu peux préciser Joana stp.
Non.
internal est l'access control par défault.
ça s'applique au module et comme les frameworks sont linked au sein du module ils ont accès aux classes déclarées internal. Sinon on devrait tout déclarer public pour utiliser Cocoa(Touch)...
Maintenant effectivement les classes déclarées internal ne seront pas accessibles dans un module externe. Et c'est là le problème. Si tu as mis cette classe dans un framework (donc un module) que tu link dans un autre module il faut que ta classe soit soit déclarée comme public. (et je pense que c'est ce que tu voulais dire Joanna )
Il faudrait nous en dire un peu plus au niveau de l'archi de ton code.
Exacte !
Le problème c'est qu'il me faut créer deux framework : un pour iOs et l'autre pour MacOs, du coup le problème ce déplace mais reste le même. Je vais devenir chèvre ou retrourner à ma bonne vielle base SQL.
PS : J'ai suivi ce lien :
http://www.swift-studies.com/blog/2014/6/30/creating-a-pure-swift-framework-for-both-ios-and-mac
Comment lire un fichier encodé avec une App Mac, dans une App iOS ?
Je ne comprend pas trop ton problème. Cela se fait tout seul, non ?
Exemple :
J'ai écrit une micro-application OSX stockant un texte dans un NSData, et le sauvant sur disque, dans le dossier Document du Mac.
Ensuite j'ai écrit une nano-application iOS pour lire ce fichier.
J'ouvre le répertoire Documente du Mac, je transfère le fichier sushis.bin dans l'application iOS, je compile, j'exécute et hop, le simulateur affiche :
Note technique : oui, je sais, il y a une pyramide de la mort dans mon code source.
Arg .. je retombe sur le même message d'erreur que toi ! Oui, cela doit provenir de NSCoder.
T'as essayé en mettant tes données dans un fichier XML ou Json ?
Sinon, il reste la possibilité d'encoder les données à la main, comme je le fait ici :
http://forum.cocoacafe.fr/topic/14467-swiftlecture-aléatoire-nsdata-dans-un-fichier/
Seb, tu as plusieurs erreurs dans ton code. Voici une version qui est, au même temps plus facile et plus correct...
J'attends que tu l'aies essayé et me donnes les retours :-*
J'ai trouvé ! </p>
Le NSData contient le nom complet de la classe l'ayant généré (NomApp.NomClasse). Pour l'utiliser dans une autre classe, il faut associer la nouvelle classe avec l'ancien nom.
Par exemple, pour désarchiver dans la classe Planete, le contenu d'un NSData créé par la classe Planete de l'application EncodeOSX, il faut utiliser cette syntaxe :
Mise en pratique :
ça fonctionne. Je viens de le tester, avec cette classe :
L'info produite sous OSX est bien récupérée avec l'application iOS :
Ouf !
En fait la question n'était pas de passer d'une application OSX à une application iOS, mais d'une application à une autre. Il se produit le même problème de nom de classe entre deux applications OSX.
Pourquoi ne pas faire un framework commun à iOS et à OSX ? (Un framework qui ne s'occuperai que de ça).
Parce que là si tu commence à hardcoder ce genre de choses ça va être super marrant à maintenir...
Nouvelle version de l'exemple plus lisible, sans la pyramide de l'enfer :
Je viens de faire un test avec un workspace, où se trouvent un framework avec deux targets, un app iOS et un app OS X.
Le framework ne contient que le code que je t'ai donné plutôt.
Les deux apps peuvent créer et lire le même fichier, étant donné qu'il faut le copier du dossier Documents de l'un vers l'autre.
Le code pour les deux apps et copié/collé et c'est comme-ci...
Tu peux mettre en commentaire, soit l'écriture, soit la lecture, selon tes souhaites
Merci à tous,
Je code pour mon plaisir, je ne pourrais m'y remettre que plus tard dans la semaine.