2010-02-19 2 views
0

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

Я использую команду, чтобы показать лист внутри 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]; 
} 

EDIT: Вот трассировку стека от аварии: http://files.spherecat1.com/prefpanestacktrace.txt

+0

Вы уверены, что нарушение сегментации связано с листом? Какова трассировка стека? (Пожалуйста, внесите изменения в свой вопрос или используйте сайт pastebin.) –

+2

Кроме того, вы не должны сохранять это предпочтение в настройках для системных настроек; вы должны сохранять их в своем собственном домене. Итак, в предпечатной области вы должны использовать CFPreferences, а не NSUserDefaults. –

+0

Хорошо, я снова вызову его и отправлю стек. Кроме того, спасибо за хедз-ап на предмет CFPreferences, я не говорил о том, что System Preferences является текущим приложением во время его работы. – vilhalmer

ответ

2

трассировка стека показывает причину вашей аварии:

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

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

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

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

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

Application Specific Information:
objc_msgSend() имя селектора: getFileSystemRepresentation:maxLength:

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

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

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

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

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

+0

Здесь так много полезной информации, что я еще не пропитал все это! Большое спасибо за отличный ответ. – vilhalmer

1
  1. Вы можете попробовать задержки открытия листа, performSelector: withObject: afterDelay: но тот Wouldn (например, медленный мак будет занимать много времени до нагрузки и т. д.

: http://gemma.apple.com/mac/library/documentation/UserExperience/Conceptual/PreferencePanes/Tasks/Sample.html это может помочь.

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

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

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

+0

Спасибо за информацию о willSelect и didSelect! Я также использую BWToolkit для других вещей, поэтому я решил, что могу использовать его здесь. Однако я рассмотрю нормальный метод. – vilhalmer

Смежные вопросы