#objective-c #macos #cocoa
#objective-c #macos #какао
Вопрос:
Я пытаюсь изменить содержимое моего Windows из другого класса, то есть подкласса NSViewController.Я пытаюсь использовать приведенный ниже код, но он ничего не делает.
[NSApplication sharedApplication]mainWindow]setContentView:[self view]]; //code in NSViewController
[NSApplication sharedApplication]mainWindow] // returns null
Я попытался добавить
[window makeMainWindow];
в классе делегата приложения, но это не поможет.
Я что-то пропустил?
PS Также я использую приведенный ниже код для вызова любой функции делегирования в моем классе,
[(appDelegate *) [[NSApplication sharedApplication]delegate]MyMethod];
но мне интересно, есть ли что-то лучше, без импорта класса делегата. Что-то вроде этого
[[NSApplication sharedApplication]delegate]MyMethod];
(выдает предупреждение)
Ответ №1:
Для метода MainWindow в документах говорится:
Этот метод может возвращать значение nil, если загрузка файла nib приложения не завершена, если приемник не активен или если приложение скрыто.
Я только что создал быстрое тестовое приложение и разместил следующий код:
NSLog(@"%@", [[NSApplication sharedApplication] mainWindow]);
в мой applicationDidFinishLaunching:aNotification
метод и в метод действия, который я подключил к кнопке в главном окне моего приложения.
При запуске значение mainWindow
было равно нулю, но когда я нажимаю кнопку (после того, как все запущено и отображается), значение mainWindow
больше не равно нулю.
NSApplication
предоставляет другие методы, которые могут быть вам полезны:
- windows
— массив всех окон;– keyWindow
— выдает окно, которое получает ввод с клавиатуры (или ноль);– windowWithWindowNumber:
— возвращает окно, соответствующее номеру окна — если вы знаете номер окна, содержимое которого вы хотите заменить, вы можете использовать это;– makeWindowsPerform:inOrder:
— отправляет сообщение в каждое окно — вы можете использовать это для проверки каждого окна, чтобы узнать, интересует ли оно вас.
Что касается вызова методов на delegate
, то то, что вы говорите, выдает предупреждение, для меня работает нормально. Например, это работает без предупреждений:
NSLog(@"%@", [[[NSApplication sharedApplication]delegate] description]);
Какое именно предупреждение вы получаете? Вы пытаетесь вызвать метод, который не существует?
Комментарии:
1. Большое спасибо. У меня только одно окно. Поэтому, вероятно, я буду использовать windows, чтобы попасть в массив, и буду использовать первый объект в массиве. Что касается методов делегата, вы пробовали его из другого класса, такого как viewcontroller? когда я вызываю его, он работает нормально, но выдает предупреждение, что делегат может не реагировать на этот метод.
2. Я понимаю, что вы имеете в виду сейчас о вызовах делегата. К сожалению, сообщение [[NSApplication sharedApplication] delegate] всегда будет возвращать объект типа NSApplicationDelegate . Вам нужно будет передать его своему делегату приложения, если вы хотите отправлять ему сообщения, специфичные для вашего делегата приложения. Возможно, вы захотите задать это как отдельный вопрос?
3. Я думаю, что единственный способ сделать это — передать NSApplicationDelegate определенному делегату и импортировать его в класс. Спасибо.
4. Есть еще один способ! вы можете [[NSApplication sharedApplication]делегировать]performSelector:@selector (selectorName)]; Если вы знаете имя селектора в своем делегате, нет необходимости включать заголовок appdelegate и приведение типов. Это будет работать.
5. Как насчет в Swift Playground? Как я могу получить ненулевое MainWindow?
Ответ №2:
Борьба с macOS только что поняла это.
Цитата Apple:
MainWindow
Свойство
Главное окно приложения. (только для чтения)
Обсуждение
Значение в этом свойстве равно нулю, если раскадровка приложения или файл nib еще не завершили загрузку. Также может быть nil, когда приложение неактивно или скрыто.
Если в вашем приложении только одно окно (которое является наиболее часто используемым случаем), используйте следующий код:
NSWindow *mainWindow = [[[NSApplication sharedApplication] windows] objectAtIndex:0];
Обещайте, что это не будет равно нулю, если приложение имеет windows.
Комментарии:
1. Я комментирую вопрос 3-летней давности, но, похоже, это тоже не работает. Разве это не должно что-то возвращать, поскольку ViewController, в который входит код, загружается к моменту, когда он пытается получить окно?
2. Вы вставляете этот код в viewDidLoad, он должен работать. Конечно, если в вашем приложении нет окон, тогда оно будет равно нулю.
3. Спасибо за ответ. Это один из методов TableView, поскольку он является делегатом NSTableView. Так что я не знаю, почему это не сработает, с окном, отображающим содержимое.
4. Я почти уверен, что вы не можете обещать, что оно не будет равным нулю.
5. Конечно, оно будет равно нулю , если в приложении нет окна … отредактировал ответ соответствующим образом.
Ответ №3:
Быстрые подходы для получения главного окна (если есть)
Главное окно приложения
guard let window = NSApplication.shared.mainWindow,
else {
// handle no main window present
}
// ... access window here
Массив окон приложения
let windowArray: [NSWindow] = NSApplication.shared.windows
guard windowArray.count > 0 else {
// hand case where no windows are present
}
let window = windowArray[0]
// ... access window here
Ответ №4:
Если свойство window еще не установлено, попробуйте отложить его до завершения загрузки приложения, например:
[myObject performSelector:@selector(theSelector) withObject:nil afterDelay:0.1];