无法一次异步下载多个 AWS S3 图像

Can't download multiple AWS S3 images at once asynchronously

所以基本上,我正在使用服务器来检索已存储的 URLs。一旦我检索到 URL(在 for 循环中),我将调用一个直接从 AWS S3 下载它们的函数。问题是,当我一次只需要下载一张图片时,效果很好;这包括我已经下载一张图片,上传另一张图片,然后返回加载主视图,两张图片正确显示的情况。当我有多个图像需要下载时(当我第一次启动应用程序时),图像数组重叠。我正在为 URL 使用一个数组,为 UIImages.

使用另一个数组

这是我的 ImageCache 代码:

class ImageCache {
    static var urlCache: Array<String> = []
    static var imageCache: Array<UIImage> = []
}

我使用这个而不是 NSCache 是因为我需要能够使用 imageCache 作为我的数据源并且我不确定如何指定 [=] 中的对象数量19=] 作为 NSCache 对象不可迭代。

无论如何,这是我调用下载函数的代码:

query.findObjectsInBackground { (results, error) in
    var imageURL: String = ""
    var count: Int = 1
    if error == nil {
        for result in results! {
            print(result)
            imageURL = result["imageURL"] as! String
            let imageKey = imageURL.components(separatedBy: "/uploads")[1]
            if !ImageCache.urlCache.contains(imageURL) {
                self.downloadImageFromS3(key: "uploads\(imageKey)", count: results!.count, current: count, url: imageURL)
            }
            count += 1
        }
    }
}

currentcount的原因是当当前索引等于for循环中的最后一个索引时,我们应该更新UICollectionView。这样,只有在下载最后一张图像时才会重新加载视图(至少这是目标)。

这是我的 downloadImageFromS3 函数:

func downloadImageFromS3(key: String, count: Int, current: Int, url: String) {
    DispatchQueue.main.async {
        let transferManager = AWSS3TransferManager.default()
        let downloadingFileURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("image.png")
        let downloadRequest = AWSS3TransferManagerDownloadRequest()
        downloadRequest!.bucket = "BUCKET_NAME"
        downloadRequest!.key = key
        downloadRequest!.downloadingFileURL = downloadingFileURL
        transferManager.download(downloadRequest!).continueWith(executor: AWSExecutor.mainThread()) { (task) -> Any? in
            if let error = task.error as NSError? {
                if error.domain == AWSS3TransferManagerErrorDomain, let code = AWSS3TransferManagerErrorType(rawValue: error.code) {
                    switch code {
                    case .cancelled, .paused:
                        break
                    default:
                        print("Error downloading: \(String(describing: downloadRequest!.key)) Error: \(error)")
                    }
                } else {
                    print("Error downloading: \(String(describing: downloadRequest!.key)) Error: \(error)")
                }
                return nil
            } else {
                let image = UIImage(contentsOfFile: downloadingFileURL.path)!
                ImageCache.urlCache.append(url)
                ImageCache.imageCache.append(image)
            }
            print("Download complete for: \(String(describing: downloadRequest!.key))")
            if current == count && ImageCache.imageCache.count == count && ImageCache.urlCache.count == count {
                self.collectionView?.reloadData()
                print(ImageCache.imageCache)
                print(ImageCache.urlCache)
            }
            return nil
        }
    }
}

编辑: 我想我把行

解决了
self.collectionView.reloadData()

在我之前解释的 if 声明之外。这会导致最后两张图片被弄乱,这意味着第一张和第二张图片看起来不错,但第三张和第四张图片是同一张图片。有没有人有任何解决方案来完成这项工作?

编辑: 我刚刚发现了一些最终图像重叠的真正问题。下载图片时出现解码错误:

2018-08-10 22:26:57.826759-0500 PROJECT_NAME[81557:49209786] mapData:754: *** ImageIO - mmapped file changed (old: 8112955  new: 6209998)
2018-08-10 22:26:57.871970-0500 PROJECT_NAME[81557:49209786] [0x7fcf610c5a00] Decoding failed with error code -1
2018-08-10 22:26:57.872127-0500 PROJECT_NAME[81557:49209786] [0x7fcf610c5a00] Decoding: C0 0x10C00B20 0x0218304A 0x11111100 0x00590011 8112955
2018-08-10 22:26:57.872225-0500 PROJECT_NAME[81557:49209786] [0x7fcf610c5a00] Options: 1x-1 [00000000,10C003B6] 0001D060
2018-08-10 22:26:57.872341-0500 PROJECT_NAME[81557:49209786] imageBlockSetCreate:829: *** buffer height mismatch: rect:{0,0,4288,950}  size:{4288,2848}
2018-08-10 22:26:57.873336-0500 PROJECT_NAME[81557:49209786] [Unknown process name] img_blocks_create: Null block
CGImageProviderCopyImageBlockSet(<CGImageProvider 0x6040002ed980> (component-type = Int8, pixel-size = 4, size = [4288 x 2848]));
<CGImageBlockSet 0x6000001357c0> (size = [4288 x 2848], rect = (0, 0) x [4288, 950], count = 3) [1]
2018-08-10 22:26:57.873474-0500 PROJECT_NAME[81557:49209786] [Unknown process name] img_blocks_create: Null block
CGImageProviderCopyImageBlockSet(<CGImageProvider 0x6040002ed980> (component-type = Int8, pixel-size = 4, size = [4288 x 2848]));
<CGImageBlockSet 0x6000001357c0> (size = [4288 x 2848], rect = (0, 0) x [4288, 950], count = 3)

我的印象是错误在这一行:let image = UIImage(contentsOfFile: downloadingFileURL.path)!。图片在上传到 S3 后,Content-Encoding 设置为 base64

解决了我自己的问题。一旦我将 downloadingFileURL 路径更改为 .jpeg 文件路径并使其唯一,我就能够看到问题。我还为 UIImage 调用了错误的初始化程序。应该是 UIImage(named: downloadingFileURL.path)! 而不是 UIImage(contentsOfFile: downloadingFileURL.path)!