Aller au contenu


Photo

Ecrire et lire un banal NSDictionary dans le Pasteboard

NSDictionary NSPasteboard copier-coller serialization

  • Please log in to reply
13 réponses à ce sujet

#1 berfis

berfis

    Torréfacteur de fèves

  • Membre
  • PipPipPipPipPip
  • 702 messages
  • LocationLausanne, Suisse

Posté 07 mars 2017 - 18:54

Bonjour,

 

J'ai des objets visuels pour représenter des entités Core Data. Ces objects visuels peuvent être placés sur une pageView, un autre objet visuel, et édités (déplacés, redimentionnés, etc.).

 

Je parviens même à les stocker comme "modèles" ou "patrons" dans mon fichier de préférences. Pour cela, je transforme l'entité CD en un NSDictionary, en sérialisant les attributs (comme fonte et couleur) en NSData (fig. 1). Cela fonctionne à ravir.

 

Pour rendre l'application plus complète, je souhaite pouvoir faire du copier/coller entre deux documents (pas d'une application à l'autre: les objets ont un format propriétaire). J'ai donc essayé la même stratégie (fig. 2)

 

C'est là que ça se complique. Pas moyen d'enregistrer un NSDictionary dans le presse-papiers. J'obtiens l'erreur:

__NSDictionaryM does not implement the NSPasteboard Writing protocol

Si les éléments contenus dans un dictionnaire (NSString, NSNumber etc.) semble bénéficier de ce protocole, ce n'est pas le cas de NSDictionary…

 

Je me tourne alors vers ce qui semble être une classe "wrapper": NSPasteboardItem, qui semble être un "emballage" (à la façon d'une NSValue), mais j'ai dû mal comprendre, car j'obtiens aussi un résultat insatisfaisant: NSPasteboardItem est bien collé dans le presse-papiers, mais plus rien n'en ressort — j'ai sans doute mal lu la doc, mais elle manque cruellement d'exemples simples, et je n'ai rien trouvé de probant sur Google (fig. 3)

 

Pourquoi NSDictionary, qui pourtant peut être sans autre archivé dans une plist, rencontre-t-il de tels problèmes pour être écrit et relu dans le presse-papier ?

 

Fais-je fausse route ? Y a-t-il plus simple ? Quelque chose qui rappellerait le bon vieux:

 

FUNCTION PutScrap (length: LONGINT; theType: ResType; source: Ptr) : LONGINT; 

ou son équivalent vingt ans plus tard ?

 

Merci d'avance

Fichier(s) joint(s)

  • Fichier joint  Fig 2.png   21,68 Ko   0 téléchargement(s)
  • Fichier joint  Fig 1.png   17,95 Ko   0 téléchargement(s)
  • Fichier joint  Fig 3.png   14,37 Ko   0 téléchargement(s)

_______________________________________________________________

Applications OSX sur le site de la BDRP

AutoTextAutoVerbDemiurge et Evals


#2 devulder

devulder

    Torréfacteur de fèves

  • Membre
  • PipPipPipPipPip
  • 564 messages
  • LocationViry Chatillon Essonnes

Posté 07 mars 2017 - 20:03

Hello,

 

Visiblement il faut mettre le protocole NSPasteboardWriting,NSPasteboardReading

 

Une piste ici: http://stackoverflow...om-nspasteboard



#3 berfis

berfis

    Torréfacteur de fèves

  • Membre
  • PipPipPipPipPip
  • 702 messages
  • LocationLausanne, Suisse

Posté 08 mars 2017 - 02:59

devulder,

 

J'ai vu cet exemple (comme d'autres) et je n'ai pas compris grand-chose, je l'avoue.

 

J'ai un arraycontroller qui va recevoir de la pageView (via un protocole) l'ordre de copier/coller ses entités sélectionnées (self.selectedObjects), voir schéma.

 

Dés lors, je sérialise mes MO pour en faire des NSDictionaries coupés du MOC. Il me faut maintenant les coller dans le NSPasteboard. Où placer la classe MyClassObject donné par l'exemple que tu cites ?

Fichier(s) joint(s)

  • Fichier joint  Pattern.png   32,03 Ko   1 téléchargement(s)

_______________________________________________________________

Applications OSX sur le site de la BDRP

AutoTextAutoVerbDemiurge et Evals


#4 Céroce

Céroce

    Mouleur de chocolats

  • Contrôleur d'arômes
  • 5 325 messages
  • LocationSaint-Leu-d'Esserent / France

Posté 08 mars 2017 - 08:48

Je ne suis pas certain que ce soit la bonne manière de faire, mais habituellement, je sérialise le dico en utilisant NSArchiver. On obtient ainsi une NSData qu'on peut mettre dans le Pasteboard.
RenaudPradenc.com Je suis développeur iOS & Mac indépendant.

#5 berfis

berfis

    Torréfacteur de fèves

  • Membre
  • PipPipPipPipPip
  • 702 messages
  • LocationLausanne, Suisse

Posté 08 mars 2017 - 09:02

Bonjour Céroce,

Question de novice: si je veux écrire une NSArray de NSDictionary, je sérialise l'array d'un bloc, ou l'array et chaque dictionary qu'elle contient ?


_______________________________________________________________

Applications OSX sur le site de la BDRP

AutoTextAutoVerbDemiurge et Evals


#6 Céroce

Céroce

    Mouleur de chocolats

  • Contrôleur d'arômes
  • 5 325 messages
  • LocationSaint-Leu-d'Esserent / France

Posté 08 mars 2017 - 09:14

Tu peux sérialiser l'array.
RenaudPradenc.com Je suis développeur iOS & Mac indépendant.

#7 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 999 messages
  • LocationPlestin-les-Grèves (22)

Posté 08 mars 2017 - 13:37

Autre idée. Pourquoi pas mettre l'objectID de l'entité CoreData sur le Pasteboard ? Ce n'est qu'un String. Puis, on peut récupérer l'objet de sa en le collant.


  • GoodGood aime ceci

#8 colas_

colas_

    Broyeur de fèves

  • Membre
  • PipPipPipPipPipPip
  • 1 460 messages

Posté 08 mars 2017 - 14:38

Je pense que Befis veut copier des objets entre deux documents distincts.

Et, a priori les deux documents ne partagent pas le même MOC.


small-logo.png

Mathématiques pour classes prépa et enseignement supérieur sur iPad et iPhone

www.improov.fr > < Improov sur facebook >


#9 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 999 messages
  • LocationPlestin-les-Grèves (22)

Posté 08 mars 2017 - 15:08

Peut-être mais le objectId se trouve dans le persistentStoreCoordinator.

 

Et je pensais de récupérer le objet, le copier dans un nouveau et le modifier si nécessaire. 



#10 colas_

colas_

    Broyeur de fèves

  • Membre
  • PipPipPipPipPipPip
  • 1 460 messages

Posté 08 mars 2017 - 21:01

Pareil,
Deux documents différents a priori n'ont pas le même persistentCoordinator.

small-logo.png

Mathématiques pour classes prépa et enseignement supérieur sur iPad et iPhone

www.improov.fr > < Improov sur facebook >


#11 berfis

berfis

    Torréfacteur de fèves

  • Membre
  • PipPipPipPipPip
  • 702 messages
  • LocationLausanne, Suisse

Posté 11 mars 2017 - 07:55

Bonjour Joanna,

 

Autre problème: Imagine que je modifie l'objet copié avant de le coller. Je vais récupérer l'état actuel lors du collage, or c'est l'état qu'il avait au moment de la copie qui m'intéresse...


_______________________________________________________________

Applications OSX sur le site de la BDRP

AutoTextAutoVerbDemiurge et Evals


#12 berfis

berfis

    Torréfacteur de fèves

  • Membre
  • PipPipPipPipPip
  • 702 messages
  • LocationLausanne, Suisse

Posté 12 mars 2017 - 10:04

Ce n'est toujours pas gagné.

 

pour créer un dictionnaire à partir de mon entité, je fais ceci:

- (NSDictionary*) copyToDictionary
{
	NSDictionary *dictionary = [[NSEntityDescription entityForName:@"Reserve" inManagedObjectContext:self.managedObjectContext] attributesByName];
	for (NSString *key in dictionary)
	{
		id thisObject = [self valueForKey:key];
		if (thisObject)
		{
			if (![[dictionary valueForKey:key] attributeValueClassName])
				thisObject = [NSKeyedArchiver archivedDataWithRootObject:thisObject];
			[dictionary setValue:thisObject forKey:key];
		}
		else
		{
			[dictionary setValue:nil forKey:key];
		}
	}
	return dictionary;
} 

ça marche une fois, si je répète l'opération quelques secondes plus tard ça plante:

2017-03-12 09:55:02.549 Hierarchy[8443:4564743] -[NSConcreteMutableData attributeValueClassName]: unrecognized selector sent to instance 0x6000004401b0
2017-03-12 09:55:02.549 Hierarchy[8443:4564743] -[NSConcreteMutableData attributeValueClassName]: unrecognized selector sent to instance 0x6000004401b0
2017-03-12 09:55:02.551 Hierarchy[8443:4564743] (
	0   CoreFoundation                      0x00007fff9d8b8452 __exceptionPreprocess + 178
	1   libobjc.A.dylib                     0x00007fff9b7e373c objc_exception_throw + 48
	2   CoreFoundation                      0x00007fff9d92210d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
	3   CoreFoundation                      0x00007fff9d8284d1 ___forwarding___ + 1009
	4   CoreFoundation                      0x00007fff9d828058 _CF_forwarding_prep_0 + 120
	5   Hierarchy                           0x0000000100009db6 -[Reserve copyToDictionary] + 774

... et je ne vois pas pourquoi.

 

EDIT:  Ah si, je vois. La version finale est :

- (NSDictionary*) copyToDictionary
{
	NSDictionary *dictionary = [[[self entity]attributesByName]copy];
	for (NSString *key in dictionary)
	{
		id thisObject = [self valueForKey:key];
		if (thisObject)
		{
			if (![[dictionary valueForKey:key] attributeValueClassName])
				thisObject = [NSKeyedArchiver archivedDataWithRootObject:thisObject];
			[dictionary setValue:thisObject forKey:key];
		}
		else
			[dictionary setValue:nil forKey:key];
	}
	return dictionary;
}

la propriété attributesByName est (readonly, copy) mais on peut modifier les clés du dictionnaire ! Je repars d'une copie fraîche à chaque fois maintenant.


  • colas_ aime ceci

_______________________________________________________________

Applications OSX sur le site de la BDRP

AutoTextAutoVerbDemiurge et Evals


#13 Mayerick

Mayerick

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 140 messages
  • LocationLyon

Posté 12 mars 2017 - 18:20

Hello,

 

J'utilise la méthode conseillée par Céroce dans mon application. J'avais trouvé ce code sur le net et il m'avait bien aidé à comprendre le principe. Ici par exemple je sérialise l'array qui contient des custom objects qui contiennent mes dictionnaires:

-(NSMutableArray*)dataSelection {
  NSMutableArray <CustomObject*> *customObjectArray = [NSMutableArray new];

  /* some logic to get the selection */
  CustomObject *customObject = /* ... */;
  customObject.dictionnary = /* ... */ ;
  [customObjectArray addObject:customObject];
  /* some logic to get the selection */

  return customObjectArray;
}

-(void)copy:(id)sender {
  NSArray *rootObject = [self dataSelection];
  UIPasteboard *board = [UIPasteboard pasteboardWithName:@"myPasteboard" create:YES];
  NSData *tileData = [NSKeyedArchiver archivedDataWithRootObject:rootObject];
  if (tileData) {
    [board setData:tileData forPasteboardType:@"MyUniformTypeIdentifier"];
  }
}

-(void)paste:(id)sender {
  UIPasteboard *board = [UIPasteboard pasteboardWithName:@"myPasteboard" create:NO];
  NSArray *pbType = [NSArray arrayWithObject:@"MyUniformTypeIdentifier"];
  
  if ([board containsPasteboardTypes:pbType]) {
    // get data :
    NSData *tileData = [board dataForPasteboardType:@"MyUniformTypeIdentifier"];
    NSArray <CustomObject*> *customObjectArray = (NSArray *)[NSKeyedUnarchiver unarchiveObjectWithData:tileData];
    
    if (customObjectArray) {
      /* Do whatever you want with customObjectArray */
    }
  }  
}

Une fois que tu as ton dictionnaire, est-ce que cela ne ferait pas le job ?



#14 berfis

berfis

    Torréfacteur de fèves

  • Membre
  • PipPipPipPipPip
  • 702 messages
  • LocationLausanne, Suisse

Posté 13 mars 2017 - 00:23

Bonsoir,

 

J'utilise le code suivant, assez proche de ce que tu m'indiques (je ne le connaissais pas, mais je suppose qu'il n'y a pas trente-six manières de faire le travail):

- (void) copySelectionToPasteboard
{
	NSPasteboard *board = [NSPasteboard generalPasteboard];
	[board clearContents];
	[board setData:[NSKeyedArchiver archivedDataWithRootObject:[self dictionariesFromSelection]] forType:@"RSRV"];
}

- (void) pasteFromPasteboard
{
	NSPasteboard *board = [NSPasteboard generalPasteboard];
	NSData *data = [board dataForType:@"RSRV"];
	NSArray * array = (NSArray*) [NSKeyedUnarchiver unarchiveObjectWithData:data];
	[self addReserveUsingDictionaries:array];
}

_______________________________________________________________

Applications OSX sur le site de la BDRP

AutoTextAutoVerbDemiurge et Evals






Also tagged with one or more of these keywords: NSDictionary, NSPasteboard, copier-coller, serialization

0 utilisateur(s) li(sen)t ce sujet

0 membre(s), 0 invité(s), 0 utilisateur(s) anonyme(s)