我有一个收藏夹视图,其中显示了所有用户的照片。基本的东西,一个获取PHAsset并在requestImage
上使用PHCachingImageManager
来加载缩略图的数据源。
但是最近我收到了一个错误报告,当您拥有超过5000张图像并快速滚动时,UI会冻结。经过调查,我能够重现此问题,似乎主线程在调用requestImage
之后就被锁定(_lock_wait),而该调用创建的其他几十个线程(其他单元格的缩略图)正在被锁定。还锁定等待谁知道。
我尝试了几件事,但没有任何效果:
实现了UICollectionViewDataSourcePrefetching
,并使用PHCachingImageManager
在prefetchItemsAt
事件上启动了CachingImages。有趣的是,它试图一次加载更多图像,这使情况变得更糟。而cancelPrefetchingForItemsAt
(原本应该在单元格不在屏幕上时会被调用)从未被调用。
试图在速度较慢的请求上致电cancelImageRequest
,在这里也没有成功。
现在我不知道该怎么办,我可以在后台dispatch_queue上运行requestImage
,这样它就不会锁定我的主线程,但是由于该方法将自己生成另一个线程,因此感觉很奇怪< / p>
我的代码是这样的:
let requestOptions = PHImageRequestOptions()
requestOptions.resizeMode = .fast
requestOptions.deliveryMode = .opportunistic
requestOptions.isSynchronous = false
requestOptions.isNetworkAccessAllowed = true
return requestOptions
myManager.requestImage(for: asset, targetSize: CGSize(width: 375, height: 375), contentMode: .aspectFill, options: options) { /* use image */ }
ps:我不确定,但是这似乎仅在iOS 11上发生,现在我只能在iPhone X上进行复制
答案 0 :(得分:0)
原来是问题所在:GCD dispatch concurrent queue freeze with 'Dispatch Thread Soft Limit Reached: 64' in crash log
requestImage
继续创建新线程,直到达到派发线程限制并且UI冻结此_lock_wait
解决方案是设置requestOptions.isSynchronous = true
,创建并发性受限的OperationQueue并将图像获取作为作业添加到该队列中。
//somewhere like viewDidLoad
operationQueue.maxConcurrentOperationCount = 54
//when setting up the cells
operationQueue.addOperation { [weak self] in
self?.cachingImageManager.requestImage(/* params...*/) { (image) in
OperationQueue.main.addOperation {
//use image
}
}
}