Доступ к каталогу активов pathForResource

Похоже, что:

[[NSBundle mainBundle] pathForResource:@"name" ofType:@"png"];

Ничего не возвращает для ресурсов, которые находятся в каталоге ресурсов Images.xcassets. Я также попробовал:

[[NSBundle mainBundle] pathForResource:@"name" ofType:@"png" inDirectory:@"Images"];

[[NSBundle mainBundle] pathForResource:@"name" ofType:@"png" inDirectory:@"Images.xcassets"];

Но ни один из них не сработал.

У кого-нибудь был успех в поиске путей к ресурсам в каталоге?

6 ответов

Решение

Та же проблема, но я не думаю, что мы могли бы получить к нему доступ через pathForResource:, кроме ниже:

UIImage* image = [UIImage imageNamed:@"name-in-asset-catalog"];

Это было четко задокументировано:

Каждый набор в каталоге активов имеет имя. Вы можете использовать это имя для программной загрузки любого отдельного изображения, содержащегося в наборе. Чтобы загрузить изображение, вызовите метод UIImage:imageNamed:, передав имя набора, который содержит изображение.

Я обнаружил, что в пакете с компилированным приложением вышел файл с именем "Assets.car", и я думаю, что это все наборы изображений в моем проекте, и они должны были быть заархивированы или что-то еще.

Обратитесь к документации Apple:

Xcode 5 предоставляет различные функциональные возможности для каталогов активов в зависимости от цели развертывания для вашего проекта:

  • Для всех проектов отдельные изображения могут быть загружены с использованием заданных имен.
  • Для проектов с целью развертывания iOS 7 XCode компилирует ваши каталоги ресурсов в исполняемый двоичный формат файла, который сокращает время загрузки вашего приложения.

Итак, это все.

Я также ищу способ, который не использует imageNamed:Я не хочу, чтобы время выполнения кэшировало мои изображения.

Я хотел получить доступ к некоторым векторным ресурсам для создания UNNotificationAttachment с местными ресурсами, поэтому я придумал этот вспомогательный класс. Он просто получает изображение из ресурсов, сохраняет свои данные на диск и возвращает URL файла. Я надеюсь, что это помогает кому-то.

import UIKit

class AssetExtractor {

    static func createLocalUrl(forImageNamed name: String) -> URL? {

        let fileManager = FileManager.default
        let cacheDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask)[0]
        let url = cacheDirectory.appendingPathComponent("\(name).png")

        guard fileManager.fileExists(atPath: url.path) else {
            guard
                let image = UIImage(named: name),
                let data = UIImagePNGRepresentation(image)
            else { return nil }

            fileManager.createFile(atPath: url.path, contents: data, attributes: nil)
            return url
        }

        return url
    }

}
[UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@.png", [[NSBundle mainBundle] resourcePath], imgName]];

imgName: имя набора изображений, безразличное истинное имя изображения в наборе изображений.

Попробуйте использовать имя изображения, как определено в шаге "Компиляция каталога ресурсов". Вы найдете это в результатах сборки. Обязательно расшифруйте стенограмму - вы должны увидеть что-то вроде этого:

/* com.apple.actool.compilation-results */
/path/to/Debug-iphonesimulator/Your.app/LaunchImage-800-Portrait-736h@3x.png
/path/to/Debug-iphonesimulator/Your.app/LaunchImage-800-667h@2x.png
/path/to/Debug-iphonesimulator/Your.app/LaunchImage-700@2x.png
/path/to/Debug-iphonesimulator/Your.app/LaunchImage-700-568h@2x.png
/path/to/Debug-iphonesimulator/Your.app/LaunchImage-700-Landscape~ipad.png
/path/to/Debug-iphonesimulator/Your.app/LaunchImage-700-Landscape@2x~ipad.png

Протестировано с использованием +[UIImage imageNamed:] с Xcode 6.1.1.

Хотя существует файл Contents.json (см. Ниже), связанный с каждым элементом в xcassets, который содержит имена файлов изображений этого элемента, он, по-видимому, недоступен на уровне файловой системы. Все изображения помещаются в одну папку файловой системы после компиляции. Файл json генерируется автоматически и не должен редактироваться, но он предоставляет шаблон для обходного пути.

Назовите каждый файл с единообразным суффиксом, чтобы он соответствовал идиоме, масштабу и подтипу, присутствующим в файле json. Это требует ручной работы, выбрав опцию "Показать в Finder" для каждого актива и переименовав каждый файл, но после завершения вы можете использовать pathForResource в сочетании с функцией, чтобы добавить соответствующий суффикс к имени базового актива, чтобы получить соответственно- размер изображения.

Пример кода для получения пути:

NSString *imageName = @"Add to Cart";
NSString *imageSuffix = [self someMethodThatDeterminesSuffix]; // Example: "-iphone-2x-retina4"
NSString *imagePath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@%@", imageName, imageSuffix] ofType:@"png"];

Пример файла Contents.json для актива изображения "Добавить в корзину":

{
  "images" : [
    {
      "idiom" : "iphone",
      "scale" : "1x",
      "filename" : "Add to Cart-iphone-1x.png"
    },
    {
      "idiom" : "iphone",
      "scale" : "2x",
      "filename" : "Add to Cart-iphone-2x.png"
    },
    {
      "idiom" : "iphone",
      "filename" : "Add to Cart-iphone-2x-retina4.png",
      "subtype" : "retina4",
      "scale" : "2x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

В частности, для изображений запуска и значков приложений пути к изображениям доступны через ключи UILaunchImages и CFBundleIcons Info.plist соответственно. Похоже, что эти изображения генерируются индивидуально, а значения Info.plist обновляются во время сборки приложения при использовании каталогов ресурсов (и если нет, то эти ключи записываются непосредственно в пользовательский интерфейс Xcode). Возможно, вам придется написать некоторый код, чтобы определить правильный подсловарь для использования, но изображения доступны отдельно, и в этом случае вы можете избежать использования imageNamed.

Другие вопросы по тегам