2010-02-19 5 views
0

J'écris un panneau de préférences pour contrôler un script que j'ai créé, et je veux montrer une feuille au premier lancement afin que l'utilisateur puisse dire au panneau où il a installé le script. La feuille semble bien, le problème est qu'il apparaît juste après que vous cliquiez sur le bouton pour mon volet. Cela provoque des erreurs de segmentation des préférences système immédiatement. J'utilise la commande pour afficher la feuille à l'intérieur de awakeFromNib, qui peut avoir quelque chose à voir avec ça, mais je ne peux rien faire à l'intérieur de mainViewDidLoad pour l'exécuter. Des idées sur ce que je peux faire?Attendez jusqu'à ce que le panneau de préférences soit complètement visible pour montrer la feuille?

code:

- (void) awakeFromNib 
{ 
NSLog(@"hi"); 
[sheetController setParentWindow:[NSApp mainWindow]]; 
BashScript *script = [[BashScript alloc] init]; 
if (![script loadScriptFromLocation:[self retrieveScriptLocation]]) 
{ 
    NSLog(@"Error loading script."); 
} 
else { 
    [advancedEditor setString:[script getScript]]; 
} 
} 


- (NSString*) retrieveScriptLocation 
{ 
NSUserDefaults *preferences = [[NSUserDefaults standardUserDefaults] retain]; 
NSString *location = [preferences stringForKey:@"scriptLocation"]; 
if (location != nil) 
{ 
    return location; 
} 
else 
{ 
    return [self askForScript]; 
} 
} 

- (NSString*) askForScript 
{ 
[sheetController openSheet:nil]; 
} 

EDIT: Voici la trace de la pile de l'accident: http://files.spherecat1.com/prefpanestacktrace.txt

+0

Etes-vous sûr que la violation de segmentation est liée à la feuille? Quelle est la trace de la pile? (Veuillez le modifier dans votre question ou utilisez un site pastebin.) –

+2

De même, vous ne devriez pas enregistrer cette préférence dans les préférences pour les Préférences Système; vous devriez les enregistrer sous votre propre domaine. Ainsi, dans un prefpane, vous devriez utiliser CFPreferences, pas NSUserDefaults. –

+0

Très bien, je vais le provoquer à nouveau et poster la pile. En outre, merci pour le heads-up sur la chose CFPreferences, je n'ai pas cela sur le fait que les préférences du système est l'application actuelle pendant que cela fonctionne. – vilhalmer

Répondre

2

la trace de la pile révèle la cause de votre accident:

- (void) awakeFromNib 
{ 
    if (![script loadScriptFromLocation:[self retrieveScriptLocation]]) 

- (NSString*) retrieveScriptLocation 
{ 
    return [self askForScript]; 

- (NSString*) askForScript 
{ 
    [sheetController openSheet:nil]; 
} 

vous n'êtes pas retourné une valeur de cette méthode que vous avez déclaré que le retour d'une valeur. Le compilateur devrait vous avertir à ce sujet.

Le blocage se produit car la méthode renvoie des octets effectivement aléatoires (éventuellement un pointeur d'objet valide, éventuellement pas) où la valeur de retour doit être. Vous pouvez dire que cette valeur de retour était censé être une chaîne en regardant le message tenté dans la trace de la pile:

application Informations spécifiques:
nom du sélecteur objc_msgSend(): getFileSystemRepresentation:maxLength:

C'est un NSString méthode, donc quelque chose, dans ce cas, l'implémentation derrière -[NSData initWithContentsOfFile:] et -[NSFileManager contentsAtPath:] -tried pour traiter l'adresse comme celle d'un NSString. Ce n'est pas le cas, ce qui a causé le crash, et c'est parce que vous n'avez pas retourné une chaîne d'une méthode où vous l'aviez dit.

Bien sûr, vous ne pouvez pas simplement faire en sorte que la méthode renvoie une chaîne, car vous ne l'avez pas encore retournée. Vous devez refactoriser votre code pour refléter la nature asynchrone du panneau Ouvrir et des feuilles en général. Reconnaître que vous n'avez pas encore de chaîne et ne le fera pas pendant une ou plusieurs minutes; commencez simplement la feuille de panneau Ouvrir et n'essayez pas de charger le script jusqu'à ce qu'il réussisse. En un mot, essayez de charger le script, et si vous n'avez pas encore de chemin, commencez simplement la feuille de panneau Ouvrir, puis continuez avec l'autre initialisation.

Vous ne devez pas non plus supposer que le panneau Ouvrir réussira. L'utilisateur peut annuler, surtout si c'est la première fois qu'il ouvre le prefpane et qu'il veut d'abord regarder autour de lui. En fait, vous ne devriez pas montrer un panneau ouvert immédiatement sur la charge prefpane en premier lieu. Au lieu de cela, ayez une vue de sélection de dossier montrant où le script actuel est, s'il y en a une, et expliquez clairement, par son placement et son texte explicatif en dessous et éventuellement une application judicieuse de couleur, que votre programme ne peut pas fonctionner. l'utilisateur choisit un script. Laissez l'utilisateur choisir le script et ainsi activer votre programme quand ils sont prêts.

+0

Il y a tellement d'informations utiles ici que je n'ai pas encore tout trempé! Merci beaucoup pour cette excellente réponse. – vilhalmer

1
  1. Vous pouvez essayer de retarder l'ouverture de la feuille, performSelector withObject: afterDelay: mais wouldn Ne soyez pas une bonne solution (par exemple un mac lent prendrait beaucoup de temps à charge etc.

lire ce qui suit: http://gemma.apple.com/mac/library/documentation/UserExperience/Conceptual/PreferencePanes/Tasks/Sample.html il pourrait aussi aider.

Je pense que c'est mieux si vous invitiez (ouvrez la feuille) lorsque votre panneau pref ne peut pas trouver le chemin du script dans ses préférences (par exemple longueur de chemin < 1 ou chemin == nil).

Quoi qu'il en soit ce que je voudrais essayer est - (void) willSelect; qui est envoyé avant que le panneau pref soit affiché et - (void) didSelect; qui est envoyé lorsque le panneau pref est réellement affiché.

Aussi je ne vous recommandons d'utiliser BWSheetController pour vos feuilles, il est en tête non nécessaire et l'ouverture d'une feuille vous est tout aussi facile et vous pouvez définir le parentWindow dans IB (qui est juste possible avec BWSheetController?)

+0

Merci pour l'info sur willSelect et didSelect! J'utilise aussi BWToolkit pour d'autres choses, alors j'ai pensé que je pourrais aussi bien l'utiliser ici. Je vais regarder dans la méthode normale, cependant. – vilhalmer

Questions connexes