70

I added to my project a .bundle folder filled with some images. Is it correct refer to this image directly writing something like ?:

[UIImage imageNamed:@"imageInBundle.png"];

Which is the best method to access and use these images ?

pkamb
  • 33,281
  • 23
  • 160
  • 191
MatterGoal
  • 16,038
  • 19
  • 109
  • 186

13 Answers13

57

If that does not work, try

[UIImage imageNamed:@"yourbundlefile.bundle/imageInBundle.png"];

Best

Ignacio Pascual
  • 1,895
  • 1
  • 21
  • 18
57

That is correct, imageNamed: will search your main bundle. Images in your project, even if they are in different groups in your Project Navigator will be in your main bundle and can be accessed directly by name.

CarlJ
  • 9,461
  • 3
  • 33
  • 47
Joe
  • 56,979
  • 9
  • 128
  • 135
39

Apple has thankfully provided a proper API for this from iOS 8 onwards, imageNamed:inBundle:compatibleWithTraitCollection:.

It's used like so:

[UIImage               imageNamed:@"image-name"
                         inBundle:[NSBundle bundleForClass:self.class]
    compatibleWithTraitCollection:nil]

or in swift:

let image = UIImage(named: "image-name",
                    inBundle: NSBundle(forClass: type(of:self)),
                    compatibleWithTraitCollection: nil)

or in swift 5:

let image = UIImage(named: "image-name",
                    in: Bundle(for: type(of:self)),
                    compatibleWith: nil)
al_mota
  • 431
  • 1
  • 4
  • 14
JosephH
  • 37,173
  • 19
  • 130
  • 154
27

1) If you are working with bundles go to bundle target and set COMBINE_HIDPI_IMAGES to NO. In another case the image will be converted to tiff format.

2) try this code:

NSBundle *bundle = [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"YourBundle" withExtension:@"bundle"]];
NSString *imagePath = [bundle pathForResource:@"imageInBundle" ofType:@"png"];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
Oliver Pearmain
  • 19,885
  • 13
  • 86
  • 90
user1794139
  • 279
  • 3
  • 2
10

Swift 3

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

I can't get current bundle so i do this:

Bundle(for: type(of: self))
oscarr
  • 529
  • 5
  • 6
7

You'll need to follow these steps:

  • Add the image files to your Xcode project:
  • First, make sure you have the image files you want to use in your project. Drag and drop them into your Xcode project, ensuring they are added to the appropriate target.
  • Create a resource bundle:
  • Next, you'll create a resource bundle that will contain the images. To do this, follow these steps: In Xcode, go to File -> New -> Target. Select "iOS" or "macOS" in the template selection dialog. Scroll down and choose "Bundle" from the list of templates. Click "Next" and give your bundle a name (e.g., "ImageResourcesBundle").
  • Ensure that the target is added to your main app target. Add the image files to the bundle:
  • After creating the bundle, make sure to add the image files to the bundle's target. To do this, select the bundle in Xcode's project navigator, and then drag and drop the image files into the bundle's "Copy Bundle Resources" build phase.
  • Load the image from the resource bundle: Finally, you can load the image from the resource bundle using the appropriate Bundle method.

Below is an example of how to do it:

Swift Code

**

func getImageFromResourceBundle(named imageName: String) -> UIImage? {
    // Replace "ImageResourcesBundle" with the name of your resource bundle.
    guard let bundleURL = Bundle.main.url(forResource: "ImageResourcesBundle", withExtension: "bundle"),
          let resourceBundle = Bundle(url: bundleURL) else {
        return nil
    }
    
    // Load the image from the resource bundle.
    return UIImage(named: imageName, in: resourceBundle, compatibleWith: nil)
}

Objective C Code

+(UIImage*) getImageFromResourceBundle:(NSString*) imageName
{
    NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Resource" ofType:@"bundle"];
    NSString *imageString = [[NSBundle bundleWithPath:bundlePath] pathForResource:nameOfImage ofType:@"png"];
    
    UIImage *retrievedImage = [[UIImage alloc] initWithContentsOfFile: imageString];
    return retrievedImage;
}

You can then call this function to get the image from the resource bundle:

if let image = getImageFromResourceBundle(named: "imageName") {
    // Do something with the image.
} else {
    // The image couldn't be loaded.
}
Mohammad Asif
  • 91
  • 1
  • 6
6

Swift version

@AndrewMackenzie's answer didn't work me. This is what did work

let image = UIImage(named: "imageInBundle.png")
imageView.image = image

My full answer is here.

Community
  • 1
  • 1
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
5

Since I had to figure this out for Swift, thought I would add also....

if let imagePath = NSBundle.mainBundle().pathForImageResource("TestImage.png")     
{
    imageView.image = NSImage(contentsOfFile: imagePath)
}

Where I have TestImage.png in the Supporting Files group inside my bundle.

P.J.Radadiya
  • 1,493
  • 1
  • 12
  • 21
Andrew Mackenzie
  • 5,477
  • 5
  • 48
  • 70
5

For Swift 3

let prettyImage = UIImage(named: "prettyImage",
            in: Bundle(for: self),
            compatibleWith: nil)
Pavle Mijatovic
  • 773
  • 10
  • 6
2

A quick way to do it if you are going to use it a couple of times in the same viewController:

Get the image anywhere in the same class as the method below:

// this fetches the image from: MyBundle.bundle/folder/to/images/myImage.png
UIImage *myImage = [self imageFromBundle:@"MyBundle" withPath:@"folder/to/images/myImage.png"];

Method that fetches the image:

- (UIImage *)imageFromBundle:(NSString *)bundleName withPath:(NSString *)imageName
{
    NSURL *bundleURL = [[NSBundle mainBundle] URLForResource:bundleName withExtension:@"bundle"];
    NSBundle *bundle = [NSBundle bundleWithURL:bundleURL];
    NSString *imagePath = [bundle pathForResource:imageName ofType:nil];
    UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
    return image;
}

Or simply call it straight out of the bundle:

UIImage *myImage = [UIImage imageNamed:@"MyBundle.bundle/folder/to/images/myImage.png"];
emotality
  • 12,795
  • 4
  • 39
  • 60
2

If you are building a framework and you would like all instances of UIImage(named: "image") to always use your custom bundle, you can make an extension like below that will override it

// Swift 5

extension UIImage {
  convenience init?(named: String) {
    self.init(named: named, in: <#Your Bundle#>, compatibleWith: nil)
  }
}
Fonix
  • 11,447
  • 3
  • 45
  • 74
  • It's best to never override system methods with extensions since importing something that does this will change the behavior of your without you realizing it. If you do go with this approach in a framework, it would probably be best to make it `internal` instead of `public`. – Sam Soffes Nov 09 '20 at 23:07
  • 1
    @SamSoffes you are correct, not sure why i put public in the extension, that was a mistake, thanks – Fonix Nov 11 '20 at 10:48
0

This is worked for me in Swift 5

// Empty UIImage array to store the images in it.
var icons = [UIImage]()

let fileManager = FileManager.default
let bundleURL = Bundle.main.bundleURL
let assetURL = bundleURL.appendingPathComponent("MyBundle.bundle") // Bundle URL
do {
  let contents = try fileManager.contentsOfDirectory(at: assetURL,
 includingPropertiesForKeys: [URLResourceKey.nameKey, URLResourceKey.isDirectoryKey],
 options: .skipsHiddenFiles)
  for item in contents { // item is the URL of everything in MyBundle imgs or otherwise.

      let image = UIImage(contentsOfFile: item.path) // Initializing an image
      icons.append(image!) // Adding the image to the icons array
  }
}
catch let error as NSError {
  print(error)
}
Hassan ElDesouky
  • 334
  • 4
  • 17
0

I found this question when trying to solve loading images from Swift Package, so if anybode else is struggling with that as well here's how I solved it:

let image = UIImage(named: "imageName", in: Bundle.module, compatibleWith: nil)

Kent Robin
  • 2,066
  • 20
  • 19