Подождите, пока панель настроек полностью не отобразится для отображения листа? - PullRequest
0 голосов
/ 19 февраля 2010

Я пишу панель настроек для управления созданным мной сценарием и хочу показать лист при первом запуске, чтобы пользователь мог указать панели, где он установил сценарий. Лист выглядит нормально, проблема в том, что он появляется сразу после нажатия на кнопку моей панели. Это сразу вызывает системные настройки для ошибки сегментации.

Я использую команду, чтобы показать лист внутри awakeFromNib, который может иметь к этому какое-то отношение, но я не могу получить что-либо внутри mainViewDidLoad для фактического выполнения. Любые идеи о том, что я могу сделать?

Код:

- (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];
}

РЕДАКТИРОВАТЬ: Вот трассировка стека от сбоя: http://files.spherecat1.com/prefpanestacktrace.txt

Ответы [ 2 ]

2 голосов
/ 20 февраля 2010

Трассировка стека показывает причину сбоя:

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

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

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

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

Сбой происходит потому, что метод возвращает фактически случайные байты (возможно, действительный указатель объекта, возможно, нет), где должно быть возвращаемое значение. Вы можете сказать, что это возвращаемое значение должно быть строкой, посмотрев на сообщение о попытке в трассировке стека:

Информация о приложении:
objc_msgSend() имя селектора: getFileSystemRepresentation:maxLength:

Это метод NSString, поэтому что-то - в данном случае реализация за -[NSData initWithContentsOfFile:] и -[NSFileManager contentsAtPath:] - попыталось трактовать адрес как адрес NSString. Это не так, что вызвало сбой, а потому, что вы не вернули строку из метода, в котором, как вы сказали, вы это сделаете.

Конечно, вы не можете просто заставить метод возвращать строку, потому что у вас ее еще нет. Вам необходимо реорганизовать свой код, чтобы отразить асинхронный характер панели «Открыть» и листов в целом. Признайте, что у вас еще нет строки и не будет в течение одной или нескольких минут ; просто начните открывать лист панели и не пытайтесь загрузить скрипт, пока он не будет успешным.

В двух словах, попробуйте загрузить скрипт, и, если у вас еще нет пути, просто начните лист Открыть панель и затем продолжите с другой инициализацией.

Вы также не должны предполагать, что панель Open будет успешной. Пользователь может отменить, особенно если он впервые открывает предварительную панель и хочет сначала осмотреться. Фактически, вы не должны сразу показывать панель «Открыть» при загрузке префана.

Вместо этого имейте представление средства выбора файлов, показывающее, где находится текущий скрипт, если он есть, и проясните его размещением и пояснительным текстом под ним и, возможно, разумным применением цвета, что ваша программа не сможет работать, пока пользователь выбирает скрипт Позвольте пользователю выбрать сценарий и тем самым активировать вашу программу, когда они будут готовы.

1 голос
/ 20 февраля 2010
  1. Вы можете попытаться отложить открытие листа, executeSelector: withObject: afterDelay: но это не было бы хорошим решением (например, медленный Mac занял бы много времени нагрузка и т. д.

читать следующее: http://gemma.apple.com/mac/library/documentation/UserExperience/Conceptual/PreferencePanes/Tasks/Sample.html это также может помочь.

Я думаю, что было бы лучше, если бы вы подсказали (откройте лист), когда ваша предварительная панель не может найти путь сценария в его настройках (например, длина пути <1 или путь == ноль). </p>

В любом случае, я бы попробовал: (void) willSelect; который отправляется до отображения преф - (void) didSelect; который отправляется, когда фактически отображается преф-панель.

Кроме того, я бы не рекомендовал использовать BWSheetController для своих листов, это ненужные накладные расходы, и открытие листа самостоятельно так же просто, и вы можете установить parentWindow в IB (это возможно прямо с BWSheetController?)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...