#swift #macos #bundle
#swift #macos #пакет
Вопрос:
Я пишу приложение, в котором хранятся данные о других приложениях. Я могу достаточно легко найти текущее основное приложение и его информацию:
let frontApp = NSWorkspace.shared.frontmostApplication!
и оттуда я могу получить:
let currentAppName = currentApp.localizedName ?? "Dunno"
let currentAppIcon = currentApp.icon
Если приложение не находится на переднем плане, я знаю, что могу перебирать другие запущенные приложения:
let apps = NSWorkspace.shared.runningApplications
for app in apps as [NSRunningApplication] {
print(app.localizedName ?? "whatever")
print(app.bundleIdentifier ?? "bundle")
}
Я хотел бы получить ту же информацию о приложении, которое в данный момент не запущено, но для которого у меня есть идентификатор пакета. Как я могу это получить?
Ответ №1:
Сначала получите пакет приложения, используя
let bundleURL = NSWorkspace.shared.urlForApplication(withBundleIdentifier: someBundleID)!
let bundle = Bundle(url: bundleURL)!
Получив пакет, вы можете получить большинство вещей, которые вы можете получить из NSRunningApplication
:
bundleIdentifier
вы уже знаете.bundleURL
вы только что ознакомились с приведенным выше кодом.executableArchitecture
теперьbundle.executableArchitectures
во множественном числе. Поскольку оно не запущено, вы получаете все архитектуры, на которых оно может быть запущено, а не конкретную архитектуру, на которой оно запущено.executableURL
вы можете получитьbundle.executableURL
, никаких проблем нет.launchDate
,isFinishedLaunching
,processIdentifier
,ownsMenuBar
бессмысленно получать, поскольку приложение не запущено.
Теперь у нас осталось icon
и localizedName
. Методы, которые я предлагаю для их получения, менее надежны. Чтобы получить icon
, выполните
NSWorkspace.shared.icon(forFile: bundleURL.path)
Я уверен, что это дает тот же результат, что и по NSRunningApplication.icon
крайней мере в 99% случаев, но я не уверен, есть ли крайние случаи…
Получить localizedName
более ненадежно. Есть 2 способа, ни один из которых не подходит. Выберите то, которое лучше всего подходит для ваших целей
-
FileManager.default.displayName(atPath: bundleURL.path)
Это дает вам локализованное имя, но если пользователь переименует приложение, оно вернет новое имя, а не имя пакета -
Получение
CFBundleDisplayName
из пакетаlocalizedInfoDictionary
, возврат кCFBundleName
иinfoDictionary
. По какой-то причине это не дает локализованного имени, хотя я и сказалlocalizedInfoDictionary
.let infoDict = (bundle.localizedInfoDictionary ?? bundle.infoDictionary) let localizedName = infoDict?["CFBundleDisplayName"] ?? infoDict?["CFBundleName"]
Комментарии:
1. Спасибо за ваш ответ. Это сделало свое дело. Однако я обнаружил, что первый вариант получения имени действительно
.app
указывал на конец имени. Я знаю, что это не так сложно удалить.