我目前正在开发的iOS项目遇到了一个问题。它要经历一个过程,从服务器下载图像,把它们圈起来放在黑色背景上,最后保存为文件。这将遍历不同图像的超过2000个url,并且必须对每个url进行处理。问题是,似乎有一个巨大的内存泄漏的地方,我只是不知道如何解决它。内存警告在应用程序终止前触发四次。
func getRoundedPNGDataFromData(imageData: NSData) -> NSData? {
let Image: UIImage? = UIImage(data: imageData)!
let ImageFrame: CGRect = CGRectMake(0, 0, Image!.size.width, Image!.size.height)
UIGraphicsBeginImageContextWithOptions(Image!.size, false, 1.0);
let CurrentContext: CGContextRef = UIGraphicsGetCurrentContext()
CGContextSetFillColorWithColor(CurrentContext, UIColor.blackColor().CGColor)
CGContextFillRect(CurrentContext, ImageFrame)
UIBezierPath(roundedRect: ImageFrame, cornerRadius: 10.0).addClip()
Image!.drawInRect(ImageFrame)
let NewImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return UIImagePNGRepresentation(NewImage!)
}
...
var ProgressCounter: Int = 0
for OID: String in MissingThumbnails {
let CurrentProgress: CFloat = (CFloat(ProgressCounter) / CFloat(MissingThumbnails.count))
dispatch_sync(dispatch_get_main_queue(), {
progressView?.progress
progressView?.setProgress(CurrentProgress, animated: true)
})
let ThumbURL: NSURL = NSURL(string: "http://(Host):(Port)/(self.WebAPIThumbnailPath)".stringByReplacingOccurrencesOfString("${OID}", withString: OID, options: [], range: nil).stringByReplacingOccurrencesOfString("${ThumbnailNumber}", withString: self.padID(5), options: [], range: nil))!
var ThumbData: NSData? = NSData(contentsOfURL: ThumbURL)
if (ThumbData != nil) {
if (ThumbData!.length > 0) {
var RoundedPNG: NSData? = self.getRoundedPNGDataFromData(ThumbData!)
if ((RoundedPNG!.writeToFile(FSTools.getDocumentSub("(self.Structs[Paths.OBJ_THUMBNAILS])/(OID).png"), atomically: false)) == false) {
dispatch_sync(dispatch_get_main_queue(), {() -> Void in
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
delegate?.thumbnailCacheCompleted?(false)
})
}
RoundedPNG = nil
ThumbData = nil
}
}
ProgressCounter++
}
你需要在循环中添加一个autoreleasepool来允许自动释放的内存被释放。
for OID: String in MissingThumbnails {
autoreleasepool {
/* code */
}
}
自动释放的内存在当前的自动释放池范围还存在时被释放,这通常发生在运行循环中。但是,如果代码很紧凑,并且运行循环没有运行,则内存将不会及时释放。在每次迭代时添加显式的自动释放池将允许在每次循环迭代时回收这些临时自动释放的内存。