Принимаемый ответ Уоррена Бертона, использующий сильную ссылку на @NSApplicationMain
-занятый экземпляр AppDelegate, больше не работает. Я сам подтвердил это на OS X High Sierra, и Алекс Сироштан прокомментировал, что он тоже не работает в OS X Yosemite. Эта точка отказа, как заметил Тайлер Дюрден, была в этом сообщении:
Assertion failure in -[X.XApplication init], /Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1504.82.104/AppKit.subproj/NSApplication.m:1778
2017-04-08 13:25:35.761585+0100 X
[9073:1059806][General] An uncaught exception was raised 2017-04-08 13:25:35.761601+0100 X
[9073:1059806][General] Creating more than one Application
Я очень долго боролся с этим сам, но придумал два современных решения количество эксперимента.
@NSApplicationMain
с помощью обходного пути Я обнаружил, что вы можете изменить код принятого ответа для работы вокруг ошибка. Способ сделать это - не вызвать метод super.init()
в вашем классе с именем AppDelegate
.
Действительно. Я думаю, что есть слишком нетерпеливое утверждение, подсчитывающее количество шагов, сделанных AppDelegate
(или какая-то логика вдоль этих строк), и поэтому рассчитывается вызов super.init()
, а также завершение блока override init()
. У вас есть два варианта обходных путей:
super.init()
: это действительно возможно, а полностью здорово для NSObject
, по крайней мере, в macOS. Однако вы теряете возможность ссылаться на self
в блоке override init()
. init()
вообще: рассмотрите возможность выполнения процесса инициализации во время жизненного цикла, например applicationWillFinishLaunching(:)
. Я не рекомендую ни одно из них, конечно.
@NSApplicationMain
вообще @NSApplicationMain
- это просто макрос, который мы можем приблизить. К счастью, я столкнулся с сообщением Джеймса Ф. Фишера в блоге , объясняющим, как это сделать.
Если вы написали @NSApplicationMain
в любом месте, удалите его, прежде чем приступить к выполнению этих инструкций.
Info.plist
Параметр key: value для NSPrincipalClass
должен сохранять свое значение по умолчанию:
NSPrincipalClass
NSApplication
main.swift
NSApplication
] Файл ДОЛЖЕН называться main.swift
; это специальное исключение для правила Swift для «Выражения не допускаются на верхнем уровне».
import Cocoa
let myApp: NSApplication = NSApplication.shared
let myDelegate: AppDelegate = AppDelegate()
myApp.delegate = myDelegate
_ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)
Джеймс Х Фишер объясняет, ссылаясь NSApplication
документация :
[Docs]
Каждое приложение должно иметь ровно один экземпляр
NSApplication
(или подклассNSApplication
). Функцияmain()
вашей программы должна создать этот экземпляр, вызвав метод классаshared()
.[James]
Сначала
main.swift
запускаетNSApplication.shared
и назначает этотNSApplication
объектmyApp
. Обратите внимание, что документация относится к функцииmain()
, хотя в Swift нет ни одного! Эквивалентным является файлmain.swift
.Затем
main.swift
создает экземпляр классаAppDelegate
и назначает его как.delegate
вmyApp
. Теперь вы можете увидеть, почему проект по умолчанию выбирает вызов классаAppDelegate
: он установлен как.delegate
наNSApplication
.Наконец,
blockquote>main.swift
вызывает функциюNSApplicationMain(...)
. .. ФункцияNSApplicationMain(...)
является точкой входа для приложений Cocoa.NSApplicationMain(...)
никогда не возвращается; вместо этого он устанавливает цикл событий пользовательского интерфейса и, в конечном счете, выходит из функции Cexit(...)
.Дополнительно этот пост StackOverflow подробно описывает, почему
sharedApplication
исправляет ошибку «Создание нескольких приложений».... Это все, что вам нужно! Надеюсь, это поможет кому-то еще.
Я ответил на это здесь
@override
public onListViewUpdated(event: IListViewCommandSetListViewUpdatedParameters): void {
const compareOneCommand: Command = this.tryGetCommand('COMMAND_1');
if (compareOneCommand) {
// This command should be hidden unless exactly one row is selected.
compareOneCommand.visible = this.context.pageContext.list.title === 'MyList3';
}
}