2010-02-02 9 views
4

J'utilise un OpenPanel pour obtenir une URL de chemin de fichier. Cela fonctionne:Obtenir une URL depuis beginSheetModalForWindow:

[oPanel beginSheetModalForWindow:theWindow completionHandler:^(NSInteger returnCode) 
{ 
NSURL *pathToFile = nil; 

if (returnCode == NSOKButton) 
    pathToFile = [[oPanel URLs] objectAtIndex:0]; 
}]; 

Cela ne veut pas, ce qui entraîne une « cession de lecture seule variable » erreur:

NSURL *pathToFile = nil; 
[oPanel beginSheetModalForWindow:theWindow completionHandler:^(NSInteger returnCode) 
{ 
if (returnCode == NSOKButton) 
    pathToFile = [[oPanel URLs] objectAtIndex:0]; 
}]; 
return pathToFile; 

En général, toute tentative d'extraire PathToFile du contexte de Opañel a échoué . Ce n'est pas un gros problème pour les petites situations, mais à mesure que mon code grandit, je suis obligé de tout bourrer - l'analyse XML, les données de base, etc. - dans une région inappropriée. Que puis-je faire pour extraire pathToFile?

Merci.

Répondre

6

This doesn't, resulting in an 'assignment of read-only variable' error:

NSURL *pathToFile = nil; 
[oPanel beginSheetModalForWindow:theWindow completionHandler:^(NSInteger returnCode) 
{ 
if (returnCode == NSOKButton) 
    pathToFile = [[oPanel URLs] objectAtIndex:0]; 
}]; 
return pathToFile; 

Oui, parce que vous essayez d'attribuer à la copie de la variable pathToFile qui obtient fait lorsque le bloc est créé. Vous n'attribuez pas à la variable pathToFile d'origine que vous avez déclarée en dehors du bloc.

Vous pouvez utiliser the __block keyword pour laisser le bloc affecter à cette variable, mais je ne pense pas que cela aidera car beginSheetModalForWindow:completionHandler: ne bloque pas. (La documentation ne le mentionne pas, mais il n'y a pas de raison pour que la méthode se bloque, et vous pouvez vérifier que ce n'est pas le cas.) Le message revient immédiatement, pendant que le panneau est toujours en cours d'exécution. Donc, vous essayez d'affecter votre bloc completion-handler à une variable locale, mais votre méthode dans laquelle vous avez déclaré la variable locale sera probablement retournée par le bloc de temps, donc elle ne pourra pas pour travailler avec la valeur que le bloc laissera laissera dans la variable. Quoi que vous fassiez avec pathToFile devrait être soit dans le bloc lui-même, ou dans une méthode (prenant un argument NSURL *) que le bloc peut appeler.

+0

Merci. Intéressant que cela ne suive pas les lois de portée. – spamguy

+1

Scope seul ne peut pas fonctionner parce que, comme je l'ai dit, le bloc fonctionnera longtemps après que la méthode ou la fonction dans laquelle il a été créé ait fini de tourner. Ainsi, cette étendue externe n'est plus valide lorsque le bloc s'exécute. Vous pouvez utiliser '__block' quand la fonction ou la méthode appelle le bloc lui-même, mais quand il passe le bloc à être mis en file d'attente et exécuté plus tard, cela ne fonctionnera pas, car la fonction ou la méthode sera déjà terminée au moment où le bloc va assigner à la variable. –

+0

C'est plus que frustrant. Je suis essentiellement interdit de faire quoi que ce soit jusqu'à ce que j'en ai fini avec mon URL, volontiers ou non. Ainsi, des tâches telles que récupérer une URL puis cliquer sur un bouton pour l'utiliser sont impossibles. Pourquoi, Apple, pourquoi? – spamguy

1

Vous pouvez également exécuter RunModal après avoir commencé la feuille dont vous avez juste besoin pour vous assurer de terminer la feuille plus tard. De cette façon, vous n'avez pas à vous plier à la volonté d'Apple, ce n'est pas obsolète et cela devrait fonctionner parfaitement. Cela ressemble un peu au codage de la magie noire, mais cela fonctionne.