Получение URL из beginSheetModalForWindow: - PullRequest
4 голосов
/ 02 февраля 2010

Я использую OpenPanel для получения URL-адреса пути к файлу. Это работает:

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

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

Это не приводит к ошибке «назначение переменной только для чтения»:

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

Как правило, любая попытка извлечь pathToFile из контекста oPanel не удалась. Это не так уж важно для небольших ситуаций, но по мере роста моего кода я вынужден помещать все - разбор XML, данные ядра и т. Д. - в неподходящий регион. Что я могу сделать, чтобы извлечь pathToFile?

Спасибо.

Ответы [ 2 ]

6 голосов
/ 02 февраля 2010

Это не приводит к ошибке «назначение переменной только для чтения»:

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

Да, потому что вы пытаетесь присвоить копии переменной pathToFile, которая создается при создании блока. Вы не присваиваете исходной переменной pathToFile, которую вы объявили вне блока.

Вы можете использовать ключевое слово __block , чтобы позволить блоку присваивать эту переменную, но я не думаю, что это поможет, потому что beginSheetModalForWindow:completionHandler: не блокирует. (Документация не упоминает об этом, но нет причины для метода блокировать, и вы можете проверить с помощью логирования, что он этого не делает.) Сообщение возвращается немедленно, пока панель еще работает.

Итак, вы пытаетесь присвоить свой блок обработчика завершения локальной переменной, но ваш метод, в котором вы объявили локальную переменную, вероятно, вернется к выполнению блока времени, поэтому он не сможет работать со значением, которое блок оставил оставить в переменной.

Все, что вы делаете с pathToFile, должно быть либо в самом блоке, либо в методе (с аргументом NSURL *), который блок может вызвать.

1 голос
/ 05 апреля 2012

Вы также можете запустить модал после того, как вы начинаете лист, вам просто нужно убедиться, что вы закончили лист позже. Таким образом, вам не нужно подчиняться воле яблока, это не считается устаревшим и все равно должно работать идеально.

NSOpenPanel *openPanel = [NSOpenPanel openPanel];
[openPanel beginSheetModalForWindow:window completionHandler:nil];
NSInteger result = [openPanel runModal];
NSURL *url = nil;
if (result == NSFileHandlingPanelOKButton) 
{
    url = [openPanel URL];
}
[NSApp endSheet:openPanel];

Это немного похоже на кодирование черной магии, но оно работает.

...