До iOS 18 у меня был следующий код, который работал хорошо:
let icons = Bundle.main.infoDictionary!["CFBundleIcons"] as! [String: Any]
let primaryIcon = icons["CFBundlePrimaryIcon"] as! [String: Any]
let iconName = primaryIcon["CFBundleIconName"] as! String
return UIImage(named: iconName)!
iconName
— это "AppIcon"
, и он возвращает изображение размером 1024x1024. Теперь, используя базовый SDK iOS 18, UIImage(named: iconName)
равен нулю, что приводит к сбою в моем приложении.
Более подробная информация:
Я попробовал ответы из раздела Как получить UIImage AppIcon?, но результат не такой хороший. В частности, следующий код, в котором используется CFBundleIconFiles
вместо CFBundleIconName
:
let icons = Bundle.main.infoDictionary!["CFBundleIcons"] as! [String: Any]
let primaryIcon = icons["CFBundlePrimaryIcon"] as! [String: Any]
let iconFiles = primaryIcon["CFBundleIconFiles"] as! [String]
return UIImage(named: iconFiles[0])!
iconFiles[0]
возвращает AppIcon60x60
, который использует [email protected]
в основном пакете размером 120x120, что намного ниже, чем 1024x1024.
Я провел следующее исследование:
В настройке моего приложения я использую каталог ресурсов (Assets.xcassets -> AppIcon
) с файлом изображения icon1024.png
размером 1024x1024.
На вкладке General
целевой настройки я установил AppIcon
в качестве значка приложения.
в полученном продукте (файл .app
) я вижу 3 связанных файла:
Затем я использовал приложение «Asset Catelog Tinker» для проверки Assets.car
и получил один файл icon1024.png
.
Я попробовал собрать как iOS 17, так и iOS 18, и получил одинаковую структуру папок .app
.
Это означает, что при сборке с использованием базового SDK iOS 17 при вызове UIImage(named: "AppIcon")
каким-то волшебным образом загружается файл Assets.car/icon1024.png
. Однако, если я сделаю UIImage(named: "icon1024")
, или UIImage(named: "icon1024.png")
, или UIImage(named: "Assets.car/icon1024.png")
или UIImage(named: "Assets.car/icon1024.png")
, он вернет ноль.
Я не знаю, почему я работал раньше (кто-нибудь знает?), но это больше не работает при сборке для iOS 18. Так что мне делать?
@Paulw11, есть ли другие способы получить доступ к файлу значка приложения в высоком разрешении?
По общему признанию, это была интересная задача.
Действительно, значки приложений, похоже, упакованы в файл car
, и к ним невозможно получить доступ во время выполнения.
Также кажется, что в комплекте есть только несколько отдельно стоящих значков небольшого размера... но
Просматривая параметры компилятора, я нашел этот параметр:
ASSETCATALOG_COMPILER_STANDALONE_ICON_BEHAVIOR
который можно найти в:
Build Settings > Asset Catalog Compiler - Options > Standalone Icon File Behavior
и, похоже, это позволяет реализовать практически то, что мы хотим:
Определяет, создаются ли для основного значка приложения отдельные файлы PNG или ICNS, а также включается содержимое в файл Assets.car. По умолчанию небольшое подмножество размеров включено в виде отдельных файлов, что позволяет внешним инструментам управления отображать репрезентативный значок без чтения файла CAR. Для этого параметра можно установить значение «все» или «нет», чтобы включать значки большего или меньшего размера в виде отдельных файлов.
Итак, после установки этого параметра на all
мы счастливы, но имейте в виду, что это работает (я провел все тестирование), только если вы включите хотя бы один вариант, специфичный для схемы (из-за отсутствия лучшего термина).
Например, если вы установите только слот Any Appearance
, он не будет содержать копию значка 1024.
Итак, вы хотите что-то вроде этого:
и вот, наконец, мы получаем великолепную иконку 1024, отдельно стоящую в комплекте:
который, конечно, вы можете загрузить либо с помощью существующего кода (поскольку значки теперь включены в CFBundleIcons/CFBundleIconFiles
), либо напрямую через UIImage(named: "AppIcon1024x1024")
, либо с помощью любого другого связанного с Bundle
API.
Да, кстати, есть еще один флаг (Include All App Icon Assets
- ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS
), который также отображает альтернативные значки (т. е. ресурсы значков, которые не являются основными).
Знаете, почему CFBundleIconName
работал в iOS 17? Кажется волшебным, что раньше это работало
Учитывая, что iOS18 все еще находится в стадии бета-тестирования и одной из основных особенностей является то, как система обрабатывает значки приложений, это либо ошибка, либо сознательное решение (возможно, для уменьшения размеров бандлов — можно только догадываться). Хотя я бы определенно открыл для этого радар. Имейте в виду, что API (CFBundleIconName
) работает точно так же, как и раньше, теперь компилятор не включает значок найма по умолчанию.
Поскольку ios18 все еще находится в стадии бета-тестирования, вам следует оставить отзыв о бета-версии.