如何在Swift中从文件夹获取UIImage数组?

16

我有一个像这样的普通Xcode项目...

enter image description here

请注意,有一个名为“images”的文件夹(它是一个实际的文件夹,而不仅仅是一个组),其中包含25个“.png”图像。
我想做的就是用这些图像中的每一个创建一个UIimage数组。
(或者,甚至可以是图像名称或类似的数组,那也没问题 - 然后可以使用UIImage(named:)加载它们)
如何访问那个“images”文件夹?子文件夹“images/cars”呢?
我尝试了这样的代码但是没有找到任何东西...
override func viewDidLoad()
    {
    let imageArray = NSBundle.mainBundle().URLsForResourcesWithExtension(
          "png", subdirectory: "images")
    print("test...")
    for n:NSURL in imageArray!
        { print("found ..." ,n) }
    }

你能确认图片已经加载到应用程序的包中了吗? - Peter Hornsby
请看这个答案:http://stackoverflow.com/questions/30584992/programmatically-access-image-assets - user3353890
5个回答

9
我们假设图片在应用程序的资源包中。如果不是这样,您需要确保您的图像目录在目标的“Build Phases”中的“Copy Bundle Resources”中列出。 enter image description here 编辑 仅会将图像复制到应用程序捆绑包中。如果您需要根据以下代码将文件夹复制到应用程序捆绑包,则请使用下面的StackOverflow问题来正确设置它。
这为我们提供了一个URL数组,我们可以使用UIImage(data:)和NSData(contentsOfURL:)与之一起使用,以在需要时创建图像。
获取捆绑的资源路径并附加图像目录,然后获取目录的内容。
     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)
        }
    }

非常棒的答案。这些图片肯定在“复制包资源”中。但是那里没有文件夹(“复制包资源”中根本没有文件夹——只有单独的项目)。所以这段代码对我来说不起作用。它只会抛出错误... - Fattie
没问题 - 这是一个组织上的选择。 - Peter Hornsby
但是如何将一个文件夹放入复制束资源中呢?我似乎无法把它拖放进去。 - Fattie
请参考此问题 https://dev59.com/C2gu5IYBdhLWcg3w8Lav - Peter Hornsby

6
您可以按照以下步骤下载它们:
  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)")
     }
    

5
请尝试以下步骤:
1. 将您的图像注册到“Copy Bundle Resources”中。 2. 在主Bundle中添加过滤器模块。可以参考此链接:enter image description here 在我的设备上,这些步骤能够正常工作。您也可以将过滤器从“jpg”格式更改为“png”格式。
我已在iOS 10.x及其后续版本、Swift 3.0以及xcode 8.1版本进行了测试。

4
我建议不要一次性将所有图片加载到数组中。由于图像通常很大,很容易耗尽内存并导致崩溃。
除非您绝对需要一次性将所有图像加载到内存中,否则最好将路径或URL的数组保留下来,并按需逐个加载图像。
假设包含图像的文件夹在您的应用程序捆绑包中,您可以使用NSBundle方法“URLsForResourcesWithExtension:subdirectory:”获取指向图像子目录中所有文件的NSURL数组,无论使用特定文件类型还是所有文件(如果为扩展名传递nil)。
一旦您获得了文件url数组,如果需要,您可以将其映射到路径数组,然后再将其映射到图像数组。

1
嗨 Duncan,没问题,我会加载路径。任何一种方式都可以。(小图像数组也没有问题。)问题似乎在于如何将“文件夹放入应用程序捆绑包” - 在查找CopyBundleResources时,它们似乎只是单个项目。请注意我的答案底部的代码片段...好像什么都没做? - Fattie
当您创建文件夹(不是群组),就像您在截图中展示的那样,您应该选择该文件夹,进入文件检查器,并确保目标成员资格已选中以构建您的应用程序。然后,Xcode应将图像文件夹复制到您的应用程序包中(作为文件夹)。我回答中的NSBundle调用应该会给您一个NSURL数组,您可以随意处理它们(映射为路径数组,映射为图像数组,保留为URL并根据需要加载等等)。 - Duncan C
哦,当我点击任何文件夹(或组)时,我只能看到“身份和类型”面板;我只能为单个项目看到“目标成员资格”面板 :/ 虽然感谢你的帮助.. - Fattie
1
@Fattie 你解决了这个问题吗?我也遇到了完全相同的问题。 - Moondra
1
@Fattie,有趣的是我正在遇到和你一模一样的问题,当我尝试这里列出的各种解决方案时。要么我们犯了没人发现的错误,要么其他人都没有创建图像的子文件夹???(这很令人震惊) - Moondra
1
@Fattie 我想我找到了如何将您的图像文件夹放入CopyBundleResources中的方法。从层次结构窗格(您当前拥有“images”文件夹的位置)中删除该文件夹,然后直接从Finder或桌面将您的Images文件夹拖动到Copy Bundle Resource中。我成功地以这种方式将文件夹放入CopyBundle Resources中。我找到了这个资源: http://nextriot.com/2015/08/27/using-folder-references-instead-of-inidividual-files-under-copy-bundle-resources-in-xcode-to-organise-your-layout/ - Moondra

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接