16

I have an ordinary Xcode project like this ...

enter image description here

notice there's a folder (it is an actual folder - not just a group) named "images". It contains 25 ".png" images.

All I want to do is make an array of UIimage with each of those images.

(Or even, an array of the image names or similar, that would be fine - then could load them UIImage(named:)

How do I get at that folder "images"?? What about a subfolder "images/cars"?

I tried something like this but it finds nothing...

override func viewDidLoad()
    {
    let imageArray = NSBundle.mainBundle().URLsForResourcesWithExtension(
          "png", subdirectory: "images")
    print("test...")
    for n:NSURL in imageArray!
        { print("found ..." ,n) }
    }
Fattie
  • 27,874
  • 70
  • 431
  • 719

5 Answers5

9

We we assume the images are in the app's resource bundle. If not you need to make sure that your images directory is listed in the "Copy Bundle Resources" in the "Build Phases" of the target.

enter image description here

EDIT This is only going copy the images into the app bundle, if you require the folder to be copied to the app bundle per the code below then please use the follow StackOverflow question to set it up correctly.

This gives us an array of URL's that we can then use with UIImage(data:) and NSData(contentsOfURL:) to create the image when needed.

Get the bundle's resource path and append the image directory then get the contents of the directory.

     if let path = NSBundle.mainBundle().resourcePath {

        let imagePath = path + "/images"
        let url = NSURL(fileURLWithPath: imagePath)
        let fileManager = NSFileManager.defaultManager()

        let properties = [NSURLLocalizedNameKey,
                          NSURLCreationDateKey, NSURLLocalizedTypeDescriptionKey]

        do {
            let imageURLs = try fileManager.contentsOfDirectoryAtURL(url, includingPropertiesForKeys: properties, options:NSDirectoryEnumerationOptions.SkipsHiddenFiles)

            print("image URLs: \(imageURLs)")
            // Create image from URL
            var myImage =  UIImage(data: NSData(contentsOfURL: imageURLs[0])!)

        } catch let error1 as NSError {
            print(error1.description)
        }
    }
Community
  • 1
  • 1
Peter Hornsby
  • 4,208
  • 1
  • 25
  • 44
  • Awesome answer. The images are definitely in the "Copy Bundle Resources". But there is no folder in there (there are no folders at all in "Copy Bundle Resources" - only individual items). So the code does not work for me. It just throws the error... – Fattie May 23 '16 at 23:35
  • That is okay - it is an organizational choice. – Peter Hornsby May 23 '16 at 23:37
  • But how can I put a FOLDER in copy bundle resources? I can't seem to drag it in there. – Fattie May 23 '16 at 23:38
  • See this question http://stackoverflow.com/questions/10969555/resource-files-in-subdirectory-are-copied-to-root-directory-of-the-app-bundle – Peter Hornsby May 23 '16 at 23:41
6

You can follow these steps to download them:

  1. Create a new folder in finder and add all images (or folder, ... everything).

  2. Change folder name + ".bundle" (for example: YourListImage -> YourListImage.bundle).

  3. Add folder to project.

  4. Add FileManager extension:

    extension FileManager {
        func getListFileNameInBundle(bundlePath: String) -> [String] {
    
            let fileManager = FileManager.default
            let bundleURL = Bundle.main.bundleURL
            let assetURL = bundleURL.appendingPathComponent(bundlePath)
            do {
                let contents = try fileManager.contentsOfDirectory(at: assetURL, includingPropertiesForKeys: [URLResourceKey.nameKey, URLResourceKey.isDirectoryKey], options: .skipsHiddenFiles)
                return contents.map{$0.lastPathComponent}
            }
            catch {
                return []
            }
        }
    
        func getImageInBundle(bundlePath: String) -> UIImage? {
            let bundleURL = Bundle.main.bundleURL
            let assetURL = bundleURL.appendingPathComponent(bundlePath)
            return UIImage.init(contentsOfFile: assetURL.relativePath)
        }
    }
    
  5. Use:

     let fm = FileManager.default
     let listImageName = fm.getListFileNameInBundle(bundlePath: "YourListImage.bundle")
     for imgName in listImageName {
         let image = fm.getImageInBundle(bundlePath: "YourListImage.bundle/\(imgName)")
     }
    
Ten
  • 1,426
  • 1
  • 14
  • 18
5

Please try the following:

enter image description here

  1. You have to register your images to "Copy Bundle Resources".

  2. You have to add filter module in main Bundle. enter image description here

It is working well on my side. Maybe you can change filter from "jpg" format into "png" one.

I've tested on iOS 10.x later, Swift 3.0 and xcode 8.1 version.

TylerH
  • 20,799
  • 66
  • 75
  • 101
4

I would advise against loading all of your images into an array at once. Images tend to be large and it's easy to run out of memory and crash.

Unless you absolutely have to have all the images in memory at once it's better to keep an array of paths or URLs and load the images one at a time as needed.

Assuming the folder full of images is in your app bundle, you can use the NSBundle method URLsForResourcesWithExtension:subdirectory: to get an array of NSURLs to all the files in your images subdirectory, either with a specific filetype, or ALL files (if you pass nil for the extension.)

Once you have an array of file urls you can map it to an array of paths if needed, and then map that to an array of images.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • 1
    hi Duncan, sure I'll just load the paths. Either way is fine. (An array of small images would be no problem.) The problem I seem to be having is how to get a "folder in to the app bundle" - looking in CopyBundleResources, they seem to just be individual items. Notice the code fragment at the bottom of my answer .. seems to do nothing?? – Fattie May 23 '16 at 23:41
  • When you create a folder (not a group) like you show in your screenshot, you should select the folder, go the file inspector, and make sure "Target membership" is checked for the target that builds your app. Then Xcode should copy the folder of images into your app bundle (as a folder.) The NSBundle call in my answer should give you an array of NSURLs which you can then do whatever yo want with. (map to an array of paths, map to an array of images, keep as URLs and load them as needed, etc.) – Duncan C May 23 '16 at 23:45
  • Hmm; when I click on any folder (or group) at all, I only see the "Identity and Type" panel; I only see "Target Membership" panel for individual items :/ Thanks for trying to help though .. – Fattie May 23 '16 at 23:48
  • 1
    @Fattie Did you ever solve this? I'm running into the exact problem. – Moondra Sep 10 '18 at 04:37
  • 1
    @Fattie It's funny how I'm running to the same problems you were (word for word), when trying out the various solutions listed here. Either we are making a mistake no one is catching, or no one else creates a subfolder of images??? (which is shocking) – Moondra Sep 10 '18 at 04:44
  • 1
    @Fattie I think I figured out how to get your image folder into CopyBundleResources. Delete the folder from the hierarchy pane (where you currently have the "images" folder) and instead drag your Images folder directly from finder or desktop to the Copy Bundle Resource. I was able to get the folder in CopyBundle Resources that way. I found this resource: http://nextriot.com/2015/08/27/using-folder-references-instead-of-inidividual-files-under-copy-bundle-resources-in-xcode-to-organise-your-layout/ – Moondra Sep 10 '18 at 04:52
3

Swift 4

    if let path = Bundle.main.resourcePath {
        let imagePath = path + "/images"
        let url = NSURL(fileURLWithPath: imagePath)
        let fileManager = FileManager.default

        let properties = [URLResourceKey.localizedNameKey,
                          URLResourceKey.creationDateKey, 
                          URLResourceKey.localizedTypeDescriptionKey]

        do {
            let imageURLs = try fileManager.contentsOfDirectory(at: url as URL, includingPropertiesForKeys: properties, options:FileManager.DirectoryEnumerationOptions.skipsHiddenFiles)

            print("image URLs: \(imageURLs)")
            // Create image from URL
            let firstImageURL = imageURLs[0]
            let firstImageData = try Data(contentsOf: firstImageURL)
            let firstImage = UIImage(data: firstImageData)

            // Do something with first image

        } catch let error as NSError {
            print(error.description)
        }
    }
Zia
  • 14,622
  • 7
  • 40
  • 59