it-swarm.com.ru

Как использовать каталог ресурсов изображений в библиотеке cocoapod для iOS

У меня есть библиотека cocoapod, которая содержит ресурсы в 2 форматах:

  • раскадровка 
  • Каталог активов XCode .xcassets (с изображениями)

мой файл podspec содержит определение для пакета ресурсов:

s.resource_bundle = {'SparkSetup' => ['Resources/**/*.{xcassets,storyboard}']}

и у меня есть отдельная цель в проекте pod для создания пакета ресурсов, используя эти файлы + файл plist для этого пакета.

дело в том, что когда я использую модуль в проекте приложения, я вижу, что файлы раскадровки/xcassets находятся в цели модуля, и я могу легко получить доступ и запустить раскадровку, но изображения, на которые есть ссылки в раскадровке (в файле .xcassets), не найден во время выполнения (но отображается правильно в IB).

Я получаю ошибку:

Could not load the "spinner" image referenced from a nib in the bundle with identifier "(null)"

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

+(NSBundle *)getResourcesBundle
{
    NSBundle *bundle = [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"SparkSetup" withExtension:@"bundle"]];
    return bundle;
}


+(UIStoryboard *)getSetupStoryboard
{
    UIStoryboard *setupStoryboard = [UIStoryboard storyboardWithName:@"setup" bundle:[SparkSetupMainController getResourcesBundle]];
    return setupStoryboard;
}

что, кажется, хорошо подходит для поиска раскадровки, но не для поиска изображений в .xcassets в одном комплекте.

Что я делаю неправильно? Как я могу ссылаться на изображения из этой раскадровки/из кода и иметь возможность интегрировать этот модуль пользовательского интерфейса в любое приложение?

Спасибо!

22
mindbomb

По крайней мере, в версии 1.0.1 Cocoapods поддерживаются каталоги ресурсов изображений.

В своем коде Swift я использовал:

public static var GoogleIcon:UIImage {
    let bundle = NSBundle(forClass: self)
    Log.msg("bundle: \(bundle)")
    return UIImage(named: "GoogleIcon", inBundle: bundle,compatibleWithTraitCollection: nil)!
}

В своей спецификации я использовал:

s.resources = "SMCoreLib/Assets/*.xcassets"

Когда я строю с использованием симулятора, файл .car делает появляется в платформе:

cd /Users/<snip>/SMCoreLib.framework 
ls
Assets.car  Info.plist  SMCoreLib
27
Chris Prince

Ну, каталоги ресурсов изображений не поддерживаются через pods - просто включите пакет ресурсов, который содержит ваши файлы изображений в вашем podspec, например:

s.subspec 'Resources' do |resources|
    resources.resource_bundle = {'MyBundle' => ['Resources/**/*.{png}']}

end

и безопасно получить доступ к изображениям из модуля:

+(NSBundle *)getResourcesBundle
{
    NSBundle *bundle = [NSBundle bundleWithURL:[[NSBundle bundleForClass:[self class]] URLForResource:@"MyBundle" withExtension:@"bundle"]];
    return bundle;
}


+(UIImage *)loadImageFromResourceBundle:(NSString *)imageName
{
    NSBundle *bundle = [MyClass getResourcesBundle];
    NSString *imageFileName = [NSString stringWithFormat:@"%@.png",imageName];
    UIImage *image = [UIImage imageNamed:imageFileName inBundle:bundle compatibleWithTraitCollection:nil];
    return image;
}

Это решает все проблемы обработки изображений/ресурсов внутри Cocoapod.

10
mindbomb

Swift 3 версия

private func getImageFromBundle(name: String) -> UIImage {
   let podBundle = Bundle(for: YourClass.self)
   if let url = podBundle.url(forResource: "YourClass", withExtension: "bundle") {
      let bundle = Bundle(url: url)
      return UIImage(named: name, in: bundle, compatibleWith: nil)!
   }
   return UIImage()
}
4
Phil

если вы используете Swift.

class func loadImage(name: String) -> UIImage? {
    let podBundle = NSBundle(forClass: MyClass.self)
    if let url = podBundle.URLForResource("MyBundleName", withExtension: "bundle") {
        let bundle = NSBundle(URL: url)
        return UIImage(named: name, inBundle: bundle, compatibleWithTraitCollection: nil)
    }
    return nil
}
3
Daishi Nakajima

Только это работает для меня (Swift 3 и Swift 4)

public struct ImagesHelper {
  private static var podsBundle: Bundle {
    let bundle = Bundle(for: YourClass.self)
    return Bundle(url: bundle.url(forResource: "YourClass",
                                  withExtension: "bundle")!)!
  }

  private static func imageFor(name imageName: String) -> UIImage {
    return UIImage.init(named: imageName, in: podsBundle, compatibleWith: nil)!
  }

  public static var myImage: UIImage {
    return imageFor(name: "imageName")
  }
}

Тогда используйте это как ниже:

ImagesHelper.myImage

Как и в ответе @Chris Prince , не забудьте обновить файл podspec, например:

s.resource_bundles = {
  'YourClass' => ['YourPodName/*/Assets.xcassets']
}
2
pandaren codemaster

В тебе подспец так и делают

s.resources = 'RootFolder/**/*.{lproj,storyboard,xcdatamodeld,xib,xcassets,json}'
2
Abhishek Thapliyal

Я все еще не могу заставить его работать, ни одно из решений выше .. У меня есть файл Assets.xcassets в моем модуле.

И внутри моих классов Pod я хотел бы получить доступ к изображениям из активов

Указано так:

s.resource_bundles = {
     'SWDownloadPlayButton' => ['SWDownloadPlayButton/Assets/Assets.xcassets']
}

С этим помощником:

public struct ImagesHelper {
    private static var podsBundle: Bundle {
        let bundle = Bundle(for: SWDownloadPlayButton.self)
        return Bundle(url: bundle.url(forResource: "SWDownloadPlayButton",
                                      withExtension: "bundle")!)!
    }

    private static func imageFor(name imageName: String) -> UIImage {
        return UIImage.init(named: imageName, in: podsBundle, compatibleWith: nil)!
    }

    public static var download_icon: UIImage {
        return imageFor(name: "download_icon")
    }
}

Но что бы я ни делал внутри своих классов Pod (не в примере проекта) ... вот так

 var centerImage: UIImage = ImagesHelper.download_icon.withRenderingMode(.alwaysTemplate) {
        didSet {
            updateImage()
        }
    }

Я все еще получаю ноль в центре изображения

1
jr00n

Добавьте ваш файл .xcassets в ресурсы вашей спецификации pod и используйте следующий UIImage init: 

extension UIImage {
    convenience init?(podAssetName: String) {
        let podBundle = Bundle(for: ConfettiView.self)

    /// A given class within your Pod framework
    guard let url = podBundle.url(forResource: "CryptoContribute",
                                  withExtension: "bundle") else {
        return nil

    }

    self.init(named: podAssetName,
              in: Bundle(url: url),
              compatibleWith: nil)
    }
 }
0
thexande

Мое собственное решение проблемы с CocoaPods. Вместо того, чтобы связываться с UIImage, я добавил метод в Bundle. Метод пытается найти внутренний пакет с заданным именем, но возвращается к исходному пакету. Это позволяет коду работать как в коде приложения с использованием модулей, так и самого кода модуля.

extension Bundle {

    /**
     Locate an inner Bundle generated from CocoaPod packaging.

     - parameter name: the name of the inner resource bundle. This should match the "s.resource_bundle" key or
       one of the "s.resoruce_bundles" keys from the podspec file that defines the CocoPod.
     - returns: the resource Bundle or `self` if resource bundle was not found
    */
    func podResource(name: String) -> Bundle {
        guard let bundleUrl = self.url(forResource: name, withExtension: "bundle") else { return self }
        return Bundle(url: bundleUrl) ?? self
    }
}

Затем в методе viewDidLoad или где-либо еще, где у вас есть код настройки изображения, поместите что-то вроде этого, где «ClassFromPod» относится к классу Swift из CocoaPod, а «ResourceName» - это имя внутреннего пакета в модуле (вы должны иметь возможность видеть комплекты с помощью навигатора проекта Xcode в «Pods/Projects» - встроенные комплекты имеют значок LEGO и суффикс «комплекта».)

super.viewDidLoad()
let bundle = Bundle(for: ClassFromPod.self).podResource(name: "ResourceName")
img1 = UIImage(named: "FancyBase", in: bundle, compatibleWith: nil)
img2 = UIImage(named: "FancyHandle", in: bundle, compatibleWith: nil)

Как вы можете видеть, UIImage API остается прежним, только используемый пакет отличается в зависимости от того, что он находит во время выполнения.

0
Brad Howes

Вы можете получить доступ к изображениям из модулей, используя их идентификатор пакета

 enter image description here

 NSBundle * bundle = [NSBundle bundleWithIdentifier:@"bundle id of your pod"];
UIImage * image = [UIImage imageNamed:@"imageName" inBundle:bundle compatibleWithTraitCollection:nil];
0
levin varghese