[macOS] Récupérer la preview d'une NSFilePromiseReceiver avant la fin de la dragging operation
Salut à tous. En préambule, je me doute bien qu'il y a peu de chance d'avoir une réponse tant le topic est obscur. Mais je sais qu'ici certains ont des connaissances obscures, alors...
Pendant une dragging operation j'accepte les file URLs ainsi que les file promises, une URL
temporaire générée quand on drag/drop une image (ou autre) qui vient d'un autre processus comme Safari.
Typiquement on doit accepter la promise et fournir un callback qui sera appelé plus tard (idéalement) hors main queue. Ça fonctionne correctement avec ce genre de code :
filePromiseReceiver.receivePromisedFiles(atDestination: self.destinationURL, options: [:], operationQueue: self.workQueue) { (fileURL, error) in
if let error = error {
self.handleError(error)
} else {
self.handleFile(at: fileURL)
}
}
Le soucis c'est que le callback n'est appelé qu'une fois la dragging operation complétée. Et ce quel que soit le moment où receivePromisedFiles
est appelée. Toute tentative d'obtenir une preview se solde alors par un échec.
J'avais plus ou moins abandonné l'idée jusqu'à ce que par inadvertance je drag une image au dessus de la start page de Safari et que je remarque que là une preview est affichée :
(J'ai entouré en rouge la photo draguée. Oui, j'ai gardé le petit chat en fond depuis)
Me doutant bien que Safari a des passes-droit j'ai lancé mon copain Hopper et je suis allé regarder sous ses jupes. Le résultat est décevant:
Safari doit être fondu dans le système et fouiller risque d'être long.
Pour le moment j'ai trouvé qu'il ne fallait pas trop compter sur NSFilePromiseReceiver
vu que ces deux méthodes tendent à prouver qu'il fonctionne tel qu'il a été conçu:
Y'a pas plus de réponse sur le net.
Alors quelqu'un à une idée ? Obscure de préférence !
Réponses
Une idée vague, n'ayant jamais travaillé avec le glisser-déposer sur iOS. Mais sur Mac, je me souviens qu'on annonce ce qu'on va mettre dans le NSPasteboard et qu'on fournit une image pour la preview de ce qui va être glissé. Je sais que c'est un peu différent sous iOS, mais ça a l'air de s'appuyer sur les mêmes mécanismes.
Aussi, ça pourrait être intéressant de voir comment on procède sur macOS.
Alors c'est sur macOS, je l'ai pas précisé (mais mis dans la section AppKit quand même 😉). J'ajoute un tag.
Depuis macOS12
NSDraggingImage.draggedImage
est déprécié et renvoienil
quelque soit la source —du moins dans mon cas. Le fix-it d'Xcode invite laconiquement à, je-cite, Use NSDraggingItem objects instead.J'utilise
enumerateDraggingItems
deNSDraggingInfo
pour itérer les fichiers/promises et il me file desNSDraggingItem
justement. Mais même avec ça je suis pas sorti du sable.Sur ces objets on retrouve une propriété
imageComponents
qui est un[NSDraggingImageComponent]?
. S'il n'est pasnil
il content 1 ou 2 objetsNSDraggingImageComponent
qui ont une propriétékey
égale à icon ou label. J'en ai déduit que l'objet icon représente l'image et celui label le nom une image du nom de fichier vu que celui-ci est absent quand on drag une image seule.Ces objets ont aussi une propriété
contents
typéeAny
mais le debugger me dit qu'en fait c'est_CDSlotProxy
. Et personne —du moins Google, donc personne— ne sait ce qu'est un_CDSlotProxy
. Ça ne se caste en rien de connu mais par introspection on apprend que c'est unNSObject
et qu'il y a une unique propriété_slotID
. Autant dire que le mystère est complet. Il reste la pisteCGImage
mais les types CF ça devient compliqué à caster...Maintenant si tu connais une méthode pour récupérer une preview depuis le
NSPasteboard
je suis preneur !L'exemple d'Apple ne peut pas t'aider ?
https://developer.apple.com/documentation/appkit/documents_data_and_pasteboard/supporting_drag_and_drop_through_file_promises
J’ai trouvé d’autres exemples (antédiluviens) qui montrent comment modifier la drag image mais aucun ne le fait sur base de l’image en cours.
J’ai continué de creuser et j’arrive dans Carbon et plus précisément HIToolbox. Et puis c’était largement fin de journée, on verra ça demain mais ça pue…