Ma méthode pour écrire une image sur disque ne marche plus : très étrange!!
Herve
Membre
Bonjour
Je reprends en ce moment une appli crée en 2015 (non publiée). C'est un logiciel d'animation. A un moment, j'écris des images sur le disque, celles-ci sont crées dans une NSView :
- (void) creeLesImages:(int)startPlan etFin:(int)endPlan etNomFichier:(NSString *)strNom{
int nbImExtrait = endPlan - startPlan;
for (int i = 0; i < nbImExtrait; i++){
[self setPlanEnCours:(i + startPlan)];//un int pour le plan de l'animation
fileImage = [nomFichier stringByAppendingString:[NSString stringWithFormat:@"_%d.tiff", (i + startPlan]];//l'adresse de fichier plus haut
NSSize imgSize = self.bounds.size;//nous sommes dans une NSView
NSBitmapImageRep *bir = [self bitmapImageRepForCachingDisplayInRect:[self bounds]];
[bir setSize:imgSize];
[self cacheDisplayInRect:[self bounds] toBitmapImageRep:bir]; //c'est ici que drawRect est appelé
NSImage * laVue = [[NSImage alloc] initWithSize:imgSize];
[laVue addRepresentation:bir];
NSLog(@"laVue %d = %@", (i + planInit), laVue.description);//l'image est crée
BOOL imprimatur = YES;//pour vérification à cause du bugg
NSData *pdfData = [laVue TIFFRepresentation];//en console, le data apparait bien
imprimatur = [pdfData writeToFile:fileImage atomically:NO];//Il est toujours faux alors que le data est créé
NSLog(@"pdfData %d = %@\adresse = %@\nimprimé = %d", (i + planInit),pdfData.description, fileImage, imprimatur);
}
}
En console, j'ai :
laVue 49 = <NSImage 0x6000013d48c0 Size={1163, 872} RepProvider=<NSImageArrayRepProvider: 0x6000020c1a40, reps:(
"NSBitmapImageRep 0x6000009f4070 Size={1163, 872} ColorSpace=iMac colorspace BPS=8 BPP=32 Pixels=1163x872 Alpha=YES Planar=NO Format=0 CurrentBacking=<NSMutableData: 0x60000225f960>"
)
pdfData 49 = {length = 4060422, bytes = 0x4d4d002a 003de5e8 ffffffff ffffffff ... 00000002 33333400 }dresse = /Users/(...)/erty_49.tiff
imprimé = 0
J'ai vérifié l'adresse, tout fonctionne.
Cette méthode a toujours bien fonctionné et l'appli de 2015 marche normalement. J'ai "sandboxé" l'appli et ai bien autorisé l'accès aux documents, cela ne fonctionne pas mieux.
Etonnant non?
Auriez-vous une idée? Merci par avance...
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Au delà du fait qu'il existe la méthode équivalente suivante:
- (BOOL)writeToFile:(NSString *)path options:(NSDataWritingOptions)writeOptionsMask error:(NSError * _Nullable *)errorPtr;
qui te permet de récupérer une erreur, tu peux aussi (normalement) récupérer l'erreur dans Console.app.Sinon d'après la documentation ils conseillent d'utiliser un
NSFileHandle
. C'est pas obligatoire mais ça permet aux applications qui ouvrent correctement les fichiers et dossiers d'être notifiés des changements/créations/suppressions. Donc c'est un bon conseil que tu devrais suivre mais je ne pense pas que ce soit ce qui provoque le bug.[pdfData writeToFile:fileImage atomically:NO]
Cela n'écrira pas s'il existe déjà un fichier à cet endroit là (atomically
àNO
). Est-ce le cas ? Tu ne souhaites pas écraser le fichier existant ?Merci pour ta réponse, Larme.
Non, le fichier est tout neuf, il n'y a rien d'écrit encore.
Je crains que ce soit une "sécurité" quelque part, c'est pour cela que j'ai sandboxé (je me suis souvent fait avoir avec cela). Mais là, pas de progrès.
Merci aussi Pyroh. Je ne connais pas NSFileHandle, je vais voir cela.
Ce qui m'étonne, c'est que l'ancienne compilation en App fonctionne TB (dernière en date : 2020)
Et au niveau des erreurs, t'as regardé ? Parce que ta réponse est sûrement là. Aussi c'est en sandboxant une app que tu vas sacrifier ses capacités sur l'autel de la sécurité, pas le contraire.
Sinon pour
atomically
ça n'empêche pas d'écraser un fichier. À ma connaissance il n'existe pas de méthode d'écriture de fichier qui s'encombre de ce genre de détail, toutes écrasent à tout va.atomically
fait que le contenu est écrit dans un fichier temporaire et si ça se passe bien le fichier cible est supprimé et le fichier temporaire est renommé avec le nom du fichier cible. Ça évite de corrompre les fichiers.Gagné. Voici l'erreur :
"erreur = Error Domain=NSCocoaErrorDomain Code=513 "You don’t have permission to save the file “erty_49.tiff” in the folder “TestAVF”." UserInfo={NSFilePath=/Users/.../Documents/Tests Anima/TestAVF/erty_49.tiff, NSUnderlyingError=0x6000009b1b90 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}"
Bon, j'ai sandboxé. Ensuite??
Passionnant, le document en lien avec NSFileHandle, je ne connaissais pas :
https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Introduction.html#//apple_ref/doc/uid/TP40002477-SW1
Vous travaillez en fonction de ces problématiques pour votre part?
Soit tu enlève la sandbox de ton app et ça devrait normalement aller. Soit tu lis la documentation (qui est plutôt claire).
Pas toujours de gaité de coeur mais oui.
Merci Pyroh
Je lis :
"Loading kernel extensions
Loading of kernel extensions is prohibited with App Sandbox."
Mon application utilise un kernel perso pour un filtre image. Apparemment, c'est cela qui bloque. Ce serait dommage de s'en passer. J'essaie de ne pas sandboxer et je vous tiens au courant.
Effectivement si j'enlève SandBox, les images sont bien écrites. Plus de problème.
Qu'est-ce qu'un "kernel extension" comparé à CIImage? (il y a un fichier .cikernel dans l'appli, j'avais compris que c'était cela qui coinçait)
Merci en tous les cas pour cette discussion. Je relirai demain la doc.
Je reprends ce logiciel pour y mettre AVAsset (en 2015, j'utilisais QTMovie,, mais il n'est plus pris en charge) et créer le film à partir des images. Les premiers essais coinçaient également parce que le fichier du film ne pouvait être créé. J'espère que demain, cela marchera...