Je souhaite charger un exemple d'image dans une variable UIImageView
désignable de IB, à afficher dans Interface Builder lors de la modification de l'interface. Le code suivant ne fonctionne pas car l'espace réservé à la vue dans IB reste vide (la zone de vue contient uniquement le texte UIImageView):
@IBDesignable
class TestImageView : UIImageView
{
override func prepareForInterfaceBuilder() {
//let bundle = NSBundle.mainBundle()
let bundle = NSBundle(forClass: nil)
let imagePath = bundle.pathForResource("Test", ofType: "jpg")
self.image = UIImage(contentsOfFile: imagePath)
}
}
Notez que:
UIImageView
dans IB, l'image s'affiche).Ceci a été testé avec Xcode 6 beta 3.
Update : dans les deux cas, le chemin d'accès au paquet que je reçois est "/Applications/Temporary/Xcode6-Beta3.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Overlays"
. Dans ce chemin, l'image n'est évidemment pas présente.
Lorsque vous instanciez un UIImage (avec UIImage (nommé: "SomeName"), l'application recherche l'actif dans votre main bundle , ce qui fonctionne normalement. Mais lorsque vous êtes à design time , InterfaceBuilder contient le code des vues pouvant être désignées (pour compilation tant que conception ) dans un paquet séparé.
La solution est donc: Définissez votre bundle de manière dynamique , ainsi vos fichiers peuvent être trouvés dans la conception, la compilation et l'exécution:
// DYNAMIC BUNDLE DEFINITION FOR DESIGNABLE CLASS
let dynamicBundle = Bundle(for: type(of: self))
// OR ALTERNATIVELY BY PROVDING THE CONCRETE NAME OF YOUR DESIGNABLE VIEW CLASS
let dynamicBundle = Bundle(for: YourDesignableView.self)
// AND THEN SUCCESSFULLY YOU CAN LOAD THE RESSOURCE
let image = UIImage(named: "Logo", in: dynamicBundle, compatibleWith: nil)
Essayez d’obtenir le paquet de la classe comme ceci:
let bundle = NSBundle(forClass: self.dynamicType)
ou en spécifiant le nom de la classe comme ceci
let bundle = NSBundle(forClass: TestImageView.self)
En supposant que votre image se trouve dans le lot, par exemple Images.xcassets, vous pouvez ensuite la charger en utilisant:
self.image = UIImage("Test", inBundle: bundle, compatibleWithTraitCollection: self.traitCollection)
N'oubliez pas de vérifier si votre image est nulle avant d'essayer de l'utiliser. Je n'ai pas pu obtenir le chemin de l'image à l'aide de bundle.pathForResource pour fonctionner correctement avec les ressources d'image normales. Il ne semble pas non plus exister d'appel UIImage où vous spécifiez uniquement le nom et le bundle, vous devez donc utiliser la collection de traits.
Cette question est liée à:
xcode 6 IB_DESIGNABLE- ne charge pas les ressources de l'ensemble dans le générateur Interface
Réponse de Apple ...
L’ingénierie a déterminé que ce problème se comportait comme prévu sur la base Des éléments suivants:
Nous ne pouvons pas vraiment rendre cela plus facile que de spécifier le paquet. Vous Pourriez dire: "Oh, parlons-en - [NSBundle mainBundle]", mais beaucoup de sites d’appels faisant référence à un paquet ne passent pas par là (ou ne passent pas l’API des FC). On pourrait dire alors "ok, bien alors que diriez-vous de Moins swizzle - [UIImage imageNamed:]". Le problème ici est qu’il n’ya pas de remplacement unique pour le paquet principal. Vous pouvez avoir plusieurs Ensembles de vues en direct (soit des frameworks, soit des applications) chargés en même temps. Par conséquent, nous Ne pouvons pas en choisir un qui sera l'ensemble principal.
Les développeurs doivent connaître les bundles et savoir comment obtenir des images d'un Bundle. Les développeurs doivent utiliser UIImage (nommé: inBundle: compatibleWithTraitCollection :) pour toutes les recherches d’image.
Permet de faire apparaître la réponse Swift 3
let bundle = Bundle(for: self.classForCoder)
... UIImage(named: "AnImageInYourAssetsFolderPerhaps", in: bundle, compatibleWith: self.traitCollection)!
Pour Swift 4 (et 3), utilisez ceci:
let image = UIImage(named: "foo", in: Bundle(for: type(of: self)), compatibleWith: traitCollection)
Cette approche obtient le paquet universellement
J'ai pu résoudre le problème d'obtention du chemin d'accès au projet Interface Builder à partir de l'objet NSProcessInfo
actuel. Vous pouvez ensuite collecter le chemin correct à partir de la clé IB_PROJECT_SOURCE_DIRECTORIES
.
override func prepareForInterfaceBuilder() {
let processInfo = NSProcessInfo.processInfo()
let environment = processInfo.environment
let projectSourceDirectories : AnyObject = environment["IB_PROJECT_SOURCE_DIRECTORIES"]!
let directories = projectSourceDirectories.componentsSeparatedByString(":")
if directories.count != 0 {
let firstPath = directories[0] as String
let imagePath = firstPath.stringByAppendingPathComponent("PrepareForIBTest/Test.jpg")
let image = UIImage(contentsOfFile: imagePath)
self.image = image
}
}
Cette technique est décrite dans la session "Quoi de neuf dans Interface Builder" dans la session 411 de la WWDC 2014, comme suggéré par bjhomer dans ce message des forums de développement Apple .
De plus, je dois dire que il était nécessaire de passer à une sous-classe UIView
, car il semble que l'apparence de la UIImageView
ne change pas dans les vues en direct.
Pour Swift 2 et Xcode 7, l'interface a été modifiée. Devrait utiliser
let bundle = NSBundle(forClass: self.dynamicType)
let image = UIImage(named: "imageName", inBundle: bundle, compatibleWithTraitCollection: self.traitCollection)
let imageView = UIImageView(image: image)
Je l'utilise dans mon projet , cela fonctionne bien pour l'IB et l'appareil.
Cela chargera votre IB_Designable ou, si vous n’en avez pas, l’image par défaut.
- (void)prepareForInterfaceBuilder
{
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
imagePic = imagePic ? [imagePic imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] : [UIImage imageNamed:@"goodIcon" inBundle:bundle compatibleWithTraitCollection:self.traitCollection];
}