大佬教程收集整理的这篇文章主要介绍了ios – Swift:用NSOperation保留循环,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我使用NSOperation从网上下载图像.我注意到仪器公司没有发布任何NS操作.这会为下载的每个图像增加已用内存.在完成块中,我引用了“self”.所以我发现我创建了一个保留周期.
我在网上看了很多例子.我知道我可以使用“弱自我”或“无主自我”的捕获列表.我尝试了这个完成块,但仍然没有发布操作.
我的图像加载器类的代码如下:
import Foundation import UIKit class ImageLoader { lazy var downloadsInProgress = [NSIndexPath:NSOperation]() lazy var downloadQueue:NSOperationQueue = { var queue = NSOperationQueue() queue.name = "Image Download queue" return queue }() let cache = NSCache() // contains NSData objects for images init() { // Max. cache size is 10% of available physical memory (in MB's) cache.@R_620_10586@lCostLimit = 200 * 1024 * 1024 // TODO: change to 10% } /** * Download image based on url for given indexpath. * The download is only started if the indexpath is still present in the downloadsInProgress array */ func startDownloadForUrl(url: String,indexPath: NSIndexPath,completion: (imageData: NSData?) -> Void) { // check if Download request is already present if DownloadsInProgress[indexPath] != nil { return } // check cache if let imageData = self.cache.objectForKey(url) as? NSData { NSOperationQueue.mainQueue().addoperationWithBlock() { //remove indexpath from progress queue self.downloadsInProgress.removeValueForKey(indexPath) completion(imageData: imageData) } return } // prepare the download let downloader = ImageDownloader(url: url) downloader.completionBlock = { [uNowned self] in if Downloader.cancelled { return } // image is retrieved from web NSOperationQueue.mainQueue().addoperationWithBlock() { [uNowned self] in //remove indexpath from progress queue self.downloadsInProgress.removeValueForKey(indexPath) // add image to cache if Downloader.imageData != nil { self.cache.setObject(downloader.imageData!,forKey: url,cost: downloader.imageData!.length) } completion(imageData: downloader.imageData) } } // add downloader to operations in progress and start the operation NSOperationQueue.mainQueue().addoperationWithBlock() { [uNowned self] in self.downloadsInProgress[indexPath] = downloader self.downloadQueue.addoperation(downloader) } } /** * Suspends queue for downloading images */ func suspendAllOperations() { downloadQueue.suspended = true } /** * Resumes queue for downloading images */ func resumeAllOperations() { downloadQueue.suspended = false } /** * Cancels downloads for NOT visible indexpaths. The parameter specifies an array of visible indexpaths! */ func cancelDownloads(visibleIndexPaths: [NSIndexPath]) { let allPendingOperations = Set(downloadsInProgress.keys) let visiblePaths = Set(visibleIndexPaths) // cancel all pending operations for indexpaths that are not visible var toBeCancelled = allPendingOperations toBeCancelled.subtracTinPlace(visiblePaths) for indexPath in toBeCancelled { if let pendingDownloadoperation = downloadsInProgress[indexPath] { pendingDownloadoperation.cancel() } downloadsInProgress.removeValueForKey(indexPath) } } } class ImageDownloader: NSOperation { var url: String var imageData: NSData? init(url: String) { self.url = url } override func main() { if self.cancelled { return } if let imageUrl = NSURL(String: url) { // retrieve data from web setNetworkActivityInDicatorVisible(true) imageData = NSData(contentsOfURL: imageUrl) setNetworkActivityInDicatorVisible(false) if self.cancelled { imageData = nil return } // scale image if imageData != nil { if let image = UIImage(data: imageData!) { let imageData2 = UIImageJPEGRepresentation(image,1.0) let compressionRate = Float(imageData!.length) / Float(imageData2!.length) let scaleWidth = 244 / image.size.width let scaleHeight = 244 / image.size.height let imageScale = min(scaleWidth,scaleHeight) let rect = CGRectMake(0.0,0.0,image.size.width * imageScale,image.size.height * imageScalE) UIGraphicsBeginImageContext(rect.sizE) image.drawInRect(rect) let scaledImage = UIGraphicsGetImageFromCurrentImageContext() let scaledImageData = UIImageJPEGRepresentation(scaledImage,CGFloat(compressionRatE)) UIGraphicsEndImageContext() imageData = scaledImageData } } } } private func setNetworkActivityInDicatorVisible(visible: Bool) { NSOperationQueue.mainQueue().addoperationWithBlock() { let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate appDelegate.setNetworkActivityInDicatorVisible(visiblE) } } }
我究竟在哪里创建保留周期?我该如何解决这个问题?
什么时候应该使用’无主’,什么时候应该使用’弱’?
在函数startDownloadForUrl(…)中,我声明了变量下载器.接下来,我为此变量声明一个完成块.在这个完成块中,我引用了变量下载器.这导致保留周期.
我通过在完成块中使用[uNowned downloader]解决了这个问题.
这造成了另一个问题.在完成块中,我异步调用主线程.在此调用中,使用了变量downloader.imageData.由于此异步调用,NSOperation可能已经结束,并且变量下载器可能不再存在.为了避免崩溃,我为imageData声明了一个新变量,因此在主线程中使用时数据仍然可用.
完成块现在看起来像:
downloader.completionBlock = { [uNowned downloader] in if Downloader.cancelled { return } let imageData = downloader.imageData // retain the imageData. It will be used asynchrounous in the main thread. The downloader operation might already be finished and downloader will no longer exists. // image is retrieved from web NSOperationQueue.mainQueue().addoperationWithBlock() { //remove indexpath from progress queue self.downloadsInProgress.removeValueForKey(indexPath) // add image to cache if imageData != nil { self.cache.setObject(imageData!,cost: imageData!.length) } completion(imageData: imageData) } }
以上是大佬教程为你收集整理的ios – Swift:用NSOperation保留循环全部内容,希望文章能够帮你解决ios – Swift:用NSOperation保留循环所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。