[résolu] Mon appli marche dans Xcode et ne marche pas hors de Xcode

colas_colas_ Membre
avril 2013 modifié dans Apple Developer Programs #1

Bonjour,


 


  • mon appli marche si je la lance depuis Xcode
  • elle bugue si je la lance depuis le finder, en double-cliquant sur l'icône
  • elle marche si je la lance via terminal avec la commande

    ./MyProgram.app/Contents/MacOS/MyProgram


L'appli se lance mais certains fonctions ne marchent pas.


L'appli ne plante pas.


Précision sur ce qui ne marche pas :


-> création de directory


-> lancement de NSTask


 


 


 


 


C'est la première fois que je teste une appli "en-dehors" d'Xcode, donc, je n'y connais rien.


 


Est-il possible que ce soit lié à  des options de build ? Je n'ai touché à  rien, mais quand je regarde les options possible, ça me fait peut tellement c'est compliqué !!!


 


Merci !


 


Réponses

  • Tes options de sandbox ? Gatekeeper est actif sur ton Mac ?


  • CéroceCéroce Membre, Modérateur

    Par rapport à  ce que tu décris, j'ai plutôt l'impression que c'est une histoire de chemins de fichiers.


    A priori, si tu lances une appli depuis le Finder, le chemin "courant" ne sera pas le même que si tu la lances par la ligne de commande.


    Il faudrait logger quelques infos (tu peux voir les logs dans l'appli Console).


  • Tiens, je n'avais entendu parler de gatekeeper !


    Pare-feu est désactive (dans les Préférences System)


     


     


    Ou puis-je voir les options de sandbox ?


  • colas_colas_ Membre
    avril 2013 modifié #5

    Il faudrait logger quelques infos (tu peux voir les logs dans l'appli Console).


     


    Tiens ça m'intéresse ça !


    (C'est pour ça que je lançais mon appli via terminal)


    Et ça marche bien en plus !!!


     


     


    Bingo !


     


    05/04/13 13:51:04,339 dictionnaireDouchoutique: !!!! Error while creating the directory bin/6_xl0VIRY : Error Domain=NSCocoaErrorDomain Code=513 "You don't have permission to save the file “6_xl0VIRY” in the folder “bin”." UserInfo=0x1005f13a0 {NSFilePath=bin/6_xl0VIRY, NSUnderlyingError=0x1005ae2d0 "The operation couldn't be completed. Permission denied"}
  • Pour les gens qui lisent ce thread : j'ai découvert ici cette appli, mais je n'ai pas mis forum.cocoacafe.fr dessus !

    http://selfcontrolapp.com/


  • colas_colas_ Membre
    avril 2013 modifié #7

    Est-ce que ce qui suit est une ignominie ?


     


    Je souhaite que l'appli crée deux dossiers à  côté d'elle.


    (peut-être qu'il faudrait mieux que je les crée dans Library...)


    ça ne marche pas.


     



    //
    // main.m
    // dictionnaire
    //
    // Created by Colas on 25/03/13.
    //

    #import <Cocoa/Cocoa.h>

    #define kMaxIdDocument @IdMaxDocuments

    int main(int argc, char *argv[])
    {
    /*
    Création d'un dossier 'bin' et d'un dossier 'outputs'

    Code from SO :
    http://stackoverflow.com/questions/6125819/is-there-a-safer-way-to-create-a-directory-if-it-does-not-exist
    */
    @autoreleasepool
    {
    /*
    Dossier 'bin'
    */
    NSError * error = nil;
    [[NSFileManager defaultManager] createDirectoryAtPath:@bin
    withIntermediateDirectories:YES
    attributes:nil
    error:&error];
    if (error != nil)
    {
    NSLog(@"!!!! Error creating directory 'bin' : %@", error);
    }


    /*
    Dossier 'outputs'
    */
    error = nil;
    [[NSFileManager defaultManager] createDirectoryAtPath:@outputs
    withIntermediateDirectories:YES
    attributes:nil
    error:&error];
    if (error != nil)
    {
    NSLog(@"!!!! Error creating directory 'outputs' : %@", error);
    }
    }


    /*
    Enregistrement des valeurs par défaut.
    */

    @autoreleasepool
    {
    NSDictionary * defaults = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:0] forKey:kMaxIdDocument];
    [[NSUserDefaults standardUserDefaults] registerDefaults:defaults] ;
    }


    return NSApplicationMain(argc, (const char **)argv);
    }


  • AliGatorAliGator Membre, Modérateur

    Alors déjà  createDirectoryAtPath avec un chemin relatif et non absolu... C'est assez moyen. Car ça va du coup dépendre fortement du "Current Working Directory" de ton environnement et créer le dossier "bin" à  cet endroit, et je suis pas sûr que ce soit ce que tu veux ? Et c'est en général mieux de toute façon d'utiliser un chemin absolu, quitte à  le construire avec le CWD, c'est plus logique au moins tu pourras contrôler dans ta console où ça pointe, etc.


    Ca marchera avec un chemin relatif, mais faudra que tu aies conscience d'où est le Working Directory au moment où tu exécutes ton code, pour trouver ton répertoire "bin" ensuite.


     


    Sinon, est-ce bien logique de mettre tes fichiers dans "bin" ?


    Je ne sais pas ce qu'est sensée générer ton application, mais les répertoires UNIX standards ont chacun un rôle plutôt bien défini. Dans "bin" on s'attend habituellement à  trouver des exécutables, en particulier des programmes UNIX à  lancer en ligne de comande. Comme ceux qu'on trouve dans "/bin" justement. Et qui peuvent être exécutés (droits UNIX "+x").


    Pas des fichiers générés à  la volée par une application tierce comme la tinne, quoi... Enfin sauf si ton appli télécharge des binaires exécutables, à  la limite


     


    Enfin tu n'es pas sensé créer des fichiers ou dossiers à  côté de ton application OSX (ça fait très Windows, ça...).


    Une application OSX c'est un bundle contenant le binaire exécutable, les ressources de l'application (images, sons, NIB, ...) à  côté, ainsi que quelques autres trucs... le tout encapsulé dans un Bundle (c'est à  dire un dossier mais qui est vu/présenté comme un fichier unique dans le Finder).


    Or tu n'as pas le droit d'écrire dans le Bundle une fois qu'il est généré (car le Bundle est signé par Xcode justement pour empêcher les gens de modifier l'appli après coup, pour créer des chevaux de troie ou autre en hackant ton appli).


     


    Donc forcément si ton appli essaye de créer un dossier "bin" à  côté du binaire de ton application (donc dans le Bundle), ça va pas marcher (et c'est normal, encore heureux j'ai envie de dire).


     


     


     


    Utilise les dossiers "~/Library/Application Support" pour ce genre de choses. C'est fait pour ça.


    Je t'invite d'ailleurs fortement à  relire la doc Apple sur les différents emplacements et dossiers standards, leurs usages, et comment récupérer leurs chemins officiellement par code.


  • CéroceCéroce Membre, Modérateur

    En fait, je ne sais pas comment obtenir le chemin de l'appli, parce que ce n'est pas une bonne chose à  faire.


     


    Souvent, le plus simple est de demander à  l'utilisateur où enregistrer le fichier avec NSSavePanel.


    Dans ton cas, il semble plus logique de les enregister dans le répertoire ~/Library/Application Support.


     


    Code extrait de File System Programming Guide:



    - (NSURL*)applicationDataDirectory {
    NSFileManager* sharedFM = [NSFileManager defaultManager];
    NSArray* possibleURLs = [sharedFM URLsForDirectory:NSApplicationSupportDirectory
    inDomains:NSUserDomainMask];
    NSURL* appSupportDir = nil;
    NSURL* appDirectory = nil;

    if ([possibleURLs count] >= 1) {
    // Use the first directory (if multiple are returned)
    appSupportDir = [possibleURLs objectAtIndex:0];
    }

    // If a valid app support directory exists, add the
    // app's bundle ID to it to specify the final directory.
    if (appSupportDir) {
    NSString* appBundleID = [[NSBundle mainBundle] bundleIdentifier];
    appDirectory = [appSupportDir URLByAppendingPathComponent:appBundleID];
    }

    return appDirectory;
    }
  • Merci pour vos réponses !


     


    Oui vous avez raison pour Library/Application Support.


    En fait, comme j'apprends sur le tas et à  la volée, j'ai d'abord testé de créer les fichiers auxiliaires (oui : aux et non bin, merci !) à  la racine du chemin relatif.


     


    Ce qui est étonnant, c'est ce que quand je tourne l'app sous Xcode, il me crée bien "bin" à  côté de l'icône monApp (donc, à  l'extérieur du bundle), mais quand je fais autrement, ça ne marche plus... bon tant pis


     


    Sinon, est-ce acceptable "d'initialiser des choses" (créer les dossiers "aux" et "outputs") au lancement de l'appli dans main.m ?


  • AliGatorAliGator Membre, Modérateur

    Ce qui est étonnant, c'est ce que quand je tourne l'app sous Xcode, il me crée bien "bin" à  côté de l'icône monApp (donc, à  l'extérieur du bundle), mais quand je fais autrement, ça ne marche plus... bon tant pis


    Parce que Xcode n'utilise pas le même contexte lors de l'exécution de ton application que quand tu la lances par le terminal, en particulier le Working Directory qui n'est pas à  côté de ton binaire mais de ton bundle...


     


     


    Sinon, est-ce acceptable "d'initialiser des choses" (créer les dossiers "aux" et "outputs") au lancement de l'appli dans main.m ?


     


    Non pas vraiment en effet... En général pour une appli Cocoa, c'est NSApplicationMain qui gère tout, ce qui fait que le main est assez réduit et tu n'es pas sensé rajouter des choses dedans (dans 99.99% des cas tu ne le touches même pas)


     


    Utilise "application:didFinishLaunchingWithOptions:" sur le delegate de ton NSApplication (voir le protocole NSApplicationDelegate) pour exécuter du code quand ton application a fini de se lancer pour créer tes dossiers à  ce moment là .


    Et encore, si vraiment ils doivent absolument être créés dès le lancement de l'application (et pas que quand tu cliques sur un bouton) car si c'est pour les créer dès le démarrage mais que finalement l'utilisateur quitte ton appli sans rien faire et que tes dossiers ont été créés pour rien, c'est un peu dommage aussi...

  • Utilise "application:didFinishLaunchingWithOptions:" sur le delegate de ton NSApplication (voir le protocole NSApplicationDelegate) pour exécuter du code quand ton application a fini de se lancer pour créer tes dossiers à  ce moment là .


     


    Super !

Connectez-vous ou Inscrivez-vous pour répondre.