gpt4 book ai didi

ios - For 循环中的 NSURLSession 下载图像数据然后添加到 NSMutableArray

转载 作者:行者123 更新时间:2023-11-29 10:26:06 24 4
gpt4 key购买 nike

我的应用程序有一个 UITableView,其单元格包含一个 UICollectionView subview (未重用)。 collectionView 的单元格有一个 UIImageView 来保存图片。我试图一次下载所有图像,将它们存储在一个数组中,然后在 所有图像下载完毕 后在 collectionView 单元格中显示数组的内容。在 ObjC 中,我已经使用 NSURLConnection 多次执行此操作,但我正在尝试使用 Swift 和 NSURLConnection 来实现此目的,但我遇到了我认为可能是并发性或语义问题。也许你们中的某个人可以指出我正确的方向,因为我觉得我在这上面花了太多时间。

在包含我调用的 collectionView 的 UITableView 的单元格子类中

func downloadPhotosWithURLs(urls: [String]) {

var imagesMutableArray = NSMutableArray()

for url in urls {

NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: url)!, completionHandler: { (data, repsonse, err) -> Void in

if let imgData = data {

if let image = UIImage(data: imgData) {

imagesMutableArray.addObject(image)

}

else {

// PUT IN "Photo Unavailable" Pic
}
}

else {

// PUT IN "Photo Unavailable" Pic
}

}).resume()

}

// UPDATE (but async op not done)
if let downloadedImages: [UIImage] = imagesMutableArray as NSArray as? [UIImage] {

self.images = downloadedImages

dispatch_async(dispatch_get_main_queue(), { () -> Void in

self.collectionView.reloadData()
})

}

}

问题是当我要求重新加载 collectionView 时,图像还没有被获取。 for 循环中的异步操作肯定是罪魁祸首。我如何调用我的 //UPDATE 代码 after 所有图像都已下载?

最佳答案

如果要等待一系列异步任务完成,创建一个dispatch_group_t,在每次请求开始前入组,completion block 中离开组,然后就可以依赖dispatch_group_notify 当每个“enter”与“leave”匹配时调用

func downloadPhotosWithURLs(urls: [String]) {
var images = [UIImage]()

let group = dispatch_group_create()

for url in urls {
dispatch_group_enter(group)
NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: url)!, completionHandler: { data, response, error in

if let imgData = data {
if let image = UIImage(data: imgData) {
dispatch_sync(dispatch_get_main_queue()) {
images.append(image)
}
} else {
// PUT IN "Photo Unavailable" Pic
}
} else {
// PUT IN "Photo Unavailable" Pic
}

dispatch_group_leave(group)
}).resume()
}

// UPDATE
dispatch_group_notify(group, dispatch_get_main_queue()) {
self.images = images
self.collectionView.reloadData()
}
}

请注意,您确实应该同步图像数组的更新(可变数组不是线程安全的)。

--

满怀希望地回答了这个问题,我必须承认我可能会建议两个进一步但重要的改变:

  1. 您不应将图像保存在数组中(因为如果数量太多,您可能会耗尽内存)。 JPEG 或 PNG 文件可能看起来不太大,但当图像在 RAM 中解压缩时,它们会占用大量内存,您很容易收到内存警告。

    您可能会考虑将图像下载到持久存储中,而不是内存中。如果您想将图像保存在内存中,请出于性能原因使用 NSCache(但在出现内存警告时将其清除)。

    如果您没有太多图片,或者它们都很小,这可能并不重要。但是,如果您正在寻找可扩展的解决方案,则不需要您的应用将所有图像保存在一个数组中。

  2. 您可能不希望在重新加载 Collection View 之前等待所有图像。通常人们会建议延迟加载。因此,如果您有 1000 张图像,但一次只能看到 20 张,为什么要等待 1000 张图像呢?专注于加载可见细胞的图像。此外,您可能希望看到图像在下载时弹出到 Collection View 中(因此不要等待前 20 张可见图像下载完毕,而是在它们进入时显示它们)。

    您通常通过让 cellForItemAtIndexPath 异步启动图像下载并在完成后更新单元格来完成此操作。

关于ios - For 循环中的 NSURLSession 下载图像数据然后添加到 NSMutableArray,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32194003/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com