我正在尝试使用照片过滤器创建一个简单的应用,例如Instagram。所以,我捕获我的图像然后我需要对此图像实现过滤器。在底部我有一个UICollectionView(水平滚动),在那里我可以看到我有什么过滤器以及它们在我的图像上的外观。
但是当我滚动我的UICollectionView时 - 它冻结并且我的过滤器应用于每个新单元格(因为重用过程)。但是Instagram如何做到这一点当我滚动过滤器时它们不会冻结?
我试过这个:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell: imageFilterCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! imageFilterCell
let queue = NSOperationQueue()
let op1 = NSBlockOperation { () -> Void in
let img = UIImage(data: UIImageJPEGRepresentation(self.image!, 0.1)!)
let img1 = self.applyFilterTo(img!, filter: self.filtersImages[indexPath.row])
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
cell.imageView.image = img1
})
}
queue.addOperation(op1);
return cell
}
但它仍然在滚动时冻结,我看到每次我的过滤器应用于我的单元格时。我可以只做一次然后滚动无所事事,只显示实施过滤器后照片的外观吗?
答案 0 :(得分:2)
你可以做以下两件事之一:
请勿使用集合视图的重用功能。简单地创造
一系列单元格并将这些单元格传递给cellForRowAtIndexPath
。如果你这应该工作正常
没有大量的过滤器。类似的东西:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
var cell: imageFilterCell? = nil
if (cellsArray.count <= indexPath.row) {
//This assumes imageFilterCell is created in code
//If you use storyboards or xibs load it accordingly
cell = imageFilterCell()
cellsArray.append(cell)
} else {
cell = cellsArray[indexPath.row]
}
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
let img = UIImage(data: UIImageJPEGRepresentation(self.image!, 0.1)!)
let img1 = self.applyFilterTo(img!, filter: self.filtersImages[indexPath.row])
dispatch_async(dispatch_get_main_queue()) {
cell!.imageView.image = img1
}
}
return cell
}
为异步操作实现取消机制,因为如果在后台线程仍在应用过滤器的情况下重用该单元,则最终单元将最终具有多个过滤器。为此,您可以使用cancel
类中的NSOperation
方法。为此,您可以在自定义单元格上创建名为operation
的属性,例如:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell: imageFilterCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! imageFilterCell
cell.operation.cancel()
//make the queue an instance variable
//let queue = NSOperationQueue()
let op1 = NSBlockOperation { () -> Void in
let img = UIImage(data: UIImageJPEGRepresentation(self.image!, 0.1)!)
let img1 = self.applyFilterTo(img!, filter: self.filtersImages[indexPath.row])
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
cell.imageView.image = img1
})
}
queue.addOperation(op1);
cell.operation = op1
return cell
}
答案 1 :(得分:0)
你正在主线程中处理,这就是冻结的原因。
使用Concurrent Dispatch Queue获得更流畅的体验。
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell: imageFilterCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! imageFilterCell
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
let img = UIImage(data: UIImageJPEGRepresentation(self.image!, 0.1)!)
let img1 = self.applyFilterTo(img!, filter: self.filtersImages[indexPath.row])
dispatch_async(dispatch_get_main_queue()) {
cell.imageView.image = img1
}
}
return cell
}
答案 2 :(得分:0)
您可以在内存中缓存数据(图像) 它的问题与读取数据(图像)有很好的关系:D