web-dev-qa-db-fra.com

Charger une image depuis le framework iOS 8

J'essaie de charger une image à partir d'un framework iOS 8 que j'écris (sous Swift). J'utilise Xcode 6 Beta 6

Ce code ne fonctionne pas (c'est-à-dire, chargez l'image) si l'image est stockée dans le Images.xcassets de mon framework:

let image = UIImage(named: "Background.png")

Si l'image est stockée dans un Images.xcassets d'une application hôte (utilisant le cadre), l'image est chargée correctement (à partir du code situé à l'intérieur du cadre).

Je peux voir que le Images.xcassets du framework est inclus dans la phase Copy Bundle Resources.

J'utilise également un fichier de scénarimage comme ressource dans la structure; et cela se charge correctement.

J'ai essayé de renommer les ensembles Images.x du framework pour éviter certaines collisions d'attribution de nom avec l'application Host, mais cela ne fonctionne pas non plus.

30
Daniel

Bien que la réponse de @Renatus soit parfaitement valide et réponde au problème principal (il faut préciser le bundle pour le framework), je souhaitais publier la solution que j'ai choisie car elle est légèrement plus directe:

Swift 3.0/4.0

let image = UIImage(named: "YourImage", in: Bundle(for: YOURFRAMEWORKCLASS.self), compatibleWith: nil)

Vous pouvez également utiliser ce modèle pour des fonctions non -class, autrement dit non "statiques":

let image = UIImage(named: "YourImage", in: Bundle(for: type(of: self)), compatibleWith: nil)

ou ce motif pour les fonctions class:

let image = UIImage(named: "YourImage", in: Bundle(for: self), compatibleWith: nil)

Ces alternatives sont meilleures pour couper et coller.

60
Daniel

UIImage (nommé: "Background.png") appelle NSBundle.mainBundle () dans les éléments internes. Votre code essaie donc de trouver une ressource dans le bundle de votre application hôte, pas dans le bundle de frameworks. Pour charger UIImage à partir du bundle de votre framework, utilisez cet extrait:

let frameworkBundle = NSBundle(forClass: YOURFRAMEWORKCLASS.self)
let imagePath = frameworkBundle.pathForResource("yourImage.png", ofType: "")
if imagePath != nil {
  result = UIImage(contentsOfFile: imagePath!)
}

Edité: ajout d'une explication (merci à milz)

12
Renatus

Dans Swift 3.0: 

let currentBundle = Bundle(for: YOURCLASS.self)
guard let path = currentBundle.path(forResource: imageName, ofType: "jpg") else {  return defaultImage }
return UIImage(contentsOfFile: path) ?? defaultImage
2
NatashaTheRobot

Une autre option consiste à attribuer l'identifiant de paquet, ce qui est plus logique que d'attribuer une classe en termes de lisibilité.

Dans Swift 3 :

UIImage(named: "MyImage", in: Bundle(identifier: "bundleIdentifier"), compatibleWith: nil)
2
Brian

La réponse acceptée n'a pas fonctionné pour moi. Voici un moyen simple de charger une image intégrée dans un cadre dynamique:

    var bundle = NSBundle(forClass: self.classForCoder)

    if let bundlePath = NSBundle(forClass: self.classForCoder).resourcePath?.stringByAppendingString("/MYLIB.bundle"), resourceBundle = NSBundle(path: bundlePath) {
        bundle = resourceBundle
    }

    let image = UIImage(named: "my-embedded-image", inBundle: bundle, compatibleWithTraitCollection: nil)
0
Sakiboy