web-dev-qa-db-fra.com

Comment utiliser le catalogue de ressources d'images dans la bibliothèque cocoapod pour iOS

J'ai une bibliothèque de cocoapod qui contient des actifs dans 2 formats:

  • un .storyboard 
  • Catalogue de ressources XCode .xcassets (avec images)

mon fichier podspec contient la définition du groupe de ressources:

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

et j'ai une cible distincte dans le projet pod pour créer un ensemble de ressources en utilisant ces fichiers + un fichier plist pour cet ensemble.

lorsque j’utilise le pod dans un projet d’application, je peux voir les fichiers de storyboard/xcassets se trouvant dans la cible du pod et je peux accéder et exécuter le storyboard facilement, mais les images référencées dans le storyboard (dans le fichier .xcassets) sont: introuvable dans l'exécution (mais affiché correctement dans IB).

L'erreur que je reçois est:

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

Je vois un fichier bundle dans le répertoire products . Pour instancier des VC dans le story-board que j'utilise:

+(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;
}

ce qui semble bien fonctionner pour trouver le storyboard, mais pas pour trouver des images dans les .xcassets du même paquet.

Qu'est-ce que je fais mal? Comment puis-je référencer des images de ce storyboard/code et être capable d'intégrer ce pod d'interface utilisateur dans n'importe quelle application?

Merci!

22
mindbomb

À partir de la version 1.0.1 de Cocoapods, les catalogues de ressources d’image sont pris en charge.

Dans mon code Swift, j'ai utilisé:

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

Dans mes spécifications de pod, j'ai utilisé:

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

Lorsque je construis en utilisant le simulateur, le fichier .car apparaît apparaît dans le Framework:

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

Eh bien, les catalogues de ressources d’image ne sont pas pris en charge via les pods. Il suffit d’inclure un ensemble de ressources contenant vos fichiers image dans votre podspec, comme suit:

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

end

et accédez aux images en toute sécurité depuis le pod comme ça:

+(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;
}

Cela résout tous les problèmes de traitement des images/ressources au sein d'un cocoapode.

10
mindbomb

Version 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

si vous utilisez 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

Seulement ça marche pour moi (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")
  }
}

Puis utilisez-le comme ci-dessous:

ImagesHelper.myImage

Comme dans la réponse de @Chris Prince , n'oubliez pas de mettre à jour votre fichier podspec comme suit:

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

En toi podspec fais comme ça

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

Je n'arrive toujours pas à le faire fonctionner, aucune des solutions ci-dessus… .. J'ai un fichier Assets.xcassets dans mon pod.

Et dans mes cours de pod, je voudrais accéder aux images des atouts

Spécifié comme ceci:

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

Avec cette aide:

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")
    }
}

Mais quoi que je fasse dans mes classes de pods (pas dans le projet d'exemple) ... comme ceci

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

J'ai toujours un zéro au centreImage

1
jr00n

Ajoutez votre fichier .xcassets dans les ressources de votre spécification de pod et utilisez l'init UIImage suivant: 

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

Ma propre solution au problème avec CocoaPods. Au lieu de nettoyer avec UIImage, j'ai ajouté une méthode à Bundle. La méthode tente de localiser un groupe interne d'un nom donné, mais revient au groupe d'origine. Cela permet au code de fonctionner à la fois dans le code de l'application à l'aide de pods, ainsi que dans le code de pod lui-même.

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
    }
}

Ensuite, dans la méthode viewDidLoad ou partout où vous avez votre code de réglage d’image, mettez quelque chose comme ceci, où "ClassFromPod" fait référence à une classe Swift d’un CocoaPod, et "ResourceName" est le nom du paquet interne dans le être capable de voir les paquets en utilisant le navigateur de projet Xcode dans "Pods/Projects" - les paquets incorporés ont une icône LEGO et ont un suffixe "paquet".)

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)

Comme vous pouvez le constater, l'API UIImage reste la même, seul le bundle utilisé est différent en fonction de ce qu'il trouve au moment de l'exécution.

0
Brad Howes

Vous pouvez accéder aux images des pods en utilisant leur identifiant de lot.

 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