2009-10-18 10 views
0

Je suis au milieu de débogage un problème extrêmement inhabituel, et je me demandais si quelqu'un pourrait avoir une idée de ce qui pourrait aller mal:L'application modale NSPanel/sheet/dialog + NSThread == fenêtre se bloque?

Dans une classe de contrôleur à partir d'un NIB, je prends un NSPanel de cette même NIB, puis montrer app modalement sur une NSWindow (qui a été créé à la main dans le code):

[[NSApplication sharedApplication] beginSheet: myPanel 
           modalForWindow: window 
           modalDelegate: self 
           didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:) 
            contextInfo: nil]; 
[[NSApplication sharedApplication] runModalForWindow: myPanel]; 

maintenant, lorsque le bouton « terminer » sur cette feuille est cliqué, je lance un code pour désactiver certaines boutons et déclencher un thread pour s'assurer que l'entrée de l'utilisateur est valide (je dois valider avec un service distant). Ce fil est tiré à partir d'un objet validateur séparé Je crée:

// controller calls: 
[validator validateCreds: creds 
      notify: @selector(validationComplete:) 
      onObject: self]; 

// validator object 
validateInfo: (NSDictionary *)parms 
     notify: (SEL)notifySelector 
    onObject: (id)notifyObject 
{ 
// build up data with parms and notify info 
[[NSThread detachNewThreadSelector: @selector(remotevalidate:) 
      toTarget: self withObject: data]; 
} 

Ensuite, lorsque la validation est terminée, le validateur informe mon objet contrôleur:

[notifyObject performSelectorOnMainThread: notifySelector 
       withObject: results waitUntilDone: NO]; 

Et puis mon objet contrôleur, dans la méthode que les appels de l'objet validateur, tue la boîte de dialogue:

- (void)validationComplete: (id)data 
{ 
    [[NSApplication sharedApplication] stopModal]; 
    [createTwitterPanel orderOut: nil]; 
    [[NSApplication sharedApplication] endSheet: createTwitterPanel 
             returnCode: NSOKButton]; 
} 

- (void)sheetDidEnd:(NSWindow *)sheet 
     returnCode:(int)returnCode 
     contextInfo:(void *)contextInfo 
{ 
    m_returnCode = returnCode; 
} 

Mon problème: Bien que le panneau est fermé/disparait, t Le top NSApp runModalForWindow: ne se termine pas tant qu'un événement système n'est pas envoyé à la fenêtre qui affichait la boîte de dialogue. Si vous tentez de déplacer, de redimensionner ou de faire quoi que ce soit dans la fenêtre, ou si vous vous éloignez de l'application, la méthode se ferme soudainement et l'exécution se poursuit. Aucune quantité d'attente ne semble aider, sinon, cependant.

J'ai vérifié que toutes les méthodes invoquées dans la classe de contrôleur sont toutes appelées sur le thread d'application principal. Un indice encore plus intéressant est que la boîte de dialogue a deux contrôles, un WebView, et un NSTextField: Même si je force la sortie de runModalForWindow: en cliquant sur la fenêtre, TABULATION entre les deux contrôles reste vissée - ce n'est tout simplement jamais fonctionne à nouveau. C'est comme si ma boucle d'événement était bouchée.

J'ai essayé de changer validationComplete: à la place de poster une notification sur le thread principal, et j'ai également joué avec le waitUntilDone sur la méthode performSelectorOnMainThread, le tout sans effet.

Des idées? Les choses que je devrais essayer de regarder?

+0

Ceci est une application ciblée sur 10.5, exécutant Xcode 3.2.1 sur 10.6.1 – MarcWan

Répondre

2

De la documentation NSApplication:

abortModal doit être utilisé au lieu de stopModal ou stopModalWithCode: quand vous devez arrêter une boucle d'événement modal partout autre qu'une légende de cette boucle d'événements. En d'autres termes, si vous souhaitez arrêter la boucle dans réponse aux actions d'un utilisateur dans la fenêtre modale, utilisez stopModal; Sinon, utilisez abortModal. Pour exemple, utilisez abortModal lors de l'exécution dans un thread différent du thread principal du Kit d'application ou lorsque répondant à un NSTimer que vous avez ajouté au mode NSModalPanelRunLoopMode de la valeur par défaut NSRunLoop.

Donc, j'ai appris quelque chose aujourd'hui.