2015-03-08 4 views
1

Я хотел бы узнать, к какому классу может принадлежать NSObject (кроме NSAlert, NSOpenPanel и NSSavePanel), чтобы реагировать на вышеупомянутый вызов (как в заголовке вопроса). Вот сценарий того, что мне нужно сделать. Выбранное меню действие, которое должно быть модальным для . Self.window требует дополнительного ввода пользователем в форме более сложного диалога, чем «ОК/Отмена» (с простотой для рабочего кода, опущенного из примера):beginSheetModalForWindow: completeHandler:

- (IBAction)myActionDialog:(id)sender 
{ 
NSPanel *panel = self.myActionPanel; 
[panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {   
    ;   
    if (result == 0){ 
     ; 
    } 
}]; 
} 

Однако компилятор предупреждает:

'NSPanel may not respond to beginSheetModalForWindow:completionHandler' 

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

UPDATE:

Этот вопрос уважает:

[[NSApplication sharedApplication] beginSheet: modalForWindow: modalDelegate: didEndSelector: 
            contextInfo: ] 

метод, который работает практически с любым подклассу NSPanel, AFAICT. Единственная проблема заключается в том, что Apple, объявляя ее устаревшей, пока еще не задокументировала метод замещения, который заменил бы ее повсеместно, AFAIK.

+1

См. Ответ здесь, включите ссылку на пример на github http://stackoverflow.com/questions/27541684/adding-slide-down-view-in-nswindow –

+0

Спасибо @boyfarrell, это ценная ссылка и пример также ясно написано, я уже сам это выяснил, для 10.10 SDK. «Более грязная» часть проблемы заключается в обеспечении совместимости, вызывая «Gestalt» (gestaltSystemVersionMinor, & versionMinor); 'in' - (void) applicationDidFinishLaunching: (NSNotification *) aNotification', затем разветвляя код через 'if (versionMinor> .. .) {...} еще {...} '. Кстати, в связи с чем ** version minor ** старый API был удален в _NSPanel (NSWindow) _ вообще? У меня 10,6 - 10,10, за исключением 10,9. Заранее спасибо. – user3078414

+1

Я рекомендую вам не беспокоиться о наличии двух ветвей кода. Дважды код в два раза превышает вероятность ошибок. Это также затрудняет тестирование. Если вы не можете отказаться от поддержки 10.8 и более ранних версий, просто используйте старый API как свой единственный путь к коду. Когда вы отпустите поддержку 10.8 и более ранних версий, переключитесь на новый API и удалите старый API из своего кода. Если вы хотите переключиться, используйте тест, например '[NSWindow instanceRespondToSelector: @selector (beginSheet: completHandler :))' вместо проверки gestalt. Другие лучшие подходы включают сравнение «NSAppKitVersionNumber»; см. заметки о выпуске AppKit. –

ответ

2

Яблоко зарегистрировали замену на -[NSApplication beginSheet:...]. Это новые методы на NSWindow:

-beginSheet:completionHandler: 
-beginCriticalSheet:completionHandler: 
-endSheet: 
-endSheet:returnCode: 

В вашем случае, вы могли бы сделать:

[self.window beginSheet:panel completionHandler:^(NSInteger result) { 
    if (result == 0){ 
     ; 
    } 
}]; 
+0

Спасибо, @Ken Thomases. Я прочитал ** Примечания к выпуску AppKit для OSX 10.10 **, https://developer.apple.com/library/mac/releasenotes/AppKit/RN-AppKit/. Это хорошее направление в работе с этим API-интерфейсом. Тем не менее, мне все еще не ясно, если '[[NSApplication sharedApplication] beginSheet: modalForWindow: modalDelegate: didEndSelector: contextInfo:]' все еще работает с OSX 10.9. Я не пытаюсь это сделать, и это важно в решениях ветвления кода для совместимости с более ранними выпусками OSX. – user3078414

+0

Да, старые методы все еще работают. Устаревший не означает, что он сломан или отключен или непригоден для использования. Это просто означает, что вы должны работать, чтобы перейти от этих API к более новым, как вы в состоянии. В какой-то день, в будущем, эти API могут перестать работать и/или быть удалены. –

0

Это мой ответ на вопрос, после индивидуальных исследований по этому вопросу. Я нахожу серьезной проблемой при тщательном внедрении пользовательских листов, являющихся довольно внезапным и молчаливым переходом между устареванием и дисфункцией старого модального кода на основе делегата, который, должно быть, произошел где-то в течение 10.8. Это вызывает критическую проблему совместимости, требующую простого разветвления кода и воздерживаясь от чрезмерного внедрения новых перечислений API, если это действительно не требуется по какой-либо причине. Я понимаю, что такая концепция может быть не согласна с этим, но здесь есть проницательность. Я использую команду Gestalt(), потому что она работает со всеми системами между 10.7 и 10.10. Зная, что существуют более новые, более совершенные и более сложные методы определения времени выполнения ОС, вот ссылка с более релевантной информацией: https://developer.apple.com/library/mac/releasenotes/AppKit/RN-AppKit/

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

SInt32 versionMinor; 
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification 
{ 
versionMinor = 0; 
Gestalt(gestaltSystemVersionMinor, &versionMinor); 
NSLog(@"Version Minor: %d\n", (int)versionMinor); 
} 

Метод лист размещения:

- (IBAction)postSheet:(id)sender 
{ 
if(versionMinor > 8){ 
    [self.window beginSheet:self.sheet completionHandler:^(NSInteger result) { 
     if (result == 1) [self doSomething]; 
     if (result == 0) [self doNothing]; 
    }]; 
}else [[NSApplication sharedApplication] beginSheet:self.sheet 
            modalForWindow:self.window 
            modalDelegate:self 
            didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) 
             contextInfo:nil 
    ]; 
} 

кнопка OK нажата IBAction:

- (IBAction)ok:(id)sender 
{ 
[self.sheet orderOut:self]; 
if(versionMinor > 8){NSLog(@">OK Button pressed\n"); 
    [self.window endSheet:self.sheet returnCode:1]; 
}else{ NSLog(@"<OK Button pressed\n"); 
    [NSApp endSheet:self.sheet returnCode: 1]; 
    } 
} 

Аналогично, для кнопки Cancel нажимается IBAction:

- (IBAction)cancel:(id)sender 
{ 
[self.sheet orderOut:self]; 
if(versionMinor > 8){ NSLog(@">Cancel Button pressed\n"); 
    [self.window endSheet:self.sheet returnCode:0]; 
}else{ NSLog(@"<Cancel Button pressed\n"); 
    [NSApp endSheet:self.sheet returnCode: 0]; 
} 
} 

Наконец, t он «наследие» didEndSelector (для pre-10.8.время работы)

- (void)sheetDidEnd : (NSPanel*)panel returnCode:(NSInteger)returnCode contextInfo:(void*)contextInfo 
{ 
if (returnCode == 1) [self doSomething ]; 
if (returnCode == 0) [self doNothing ]; 
} 

Работает с 10.7 по 10.10, построена с SDK 10.8 или 10.10. В академических и научных сообществах OSX 10.7 и 10.8 все еще используются довольно много. Надеюсь, что кто-то найдет это полезным. Спасибо за вклад и комментарии.

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