导入数据后未释放CoreData内存

时间:2015-03-16 16:17:39

标签: ios swift core-data

我遇到了使用swift将数据导入coredata项目的问题。 我正在导入大量图像,这导致相当大的内存占用(大约100 - 120MB)。问题是,一旦下载并导入了图像,我保存了managedObjectContext并重置它,但是内存没有被释放。但是,如果我将应用程序发送到后台,大部分内存都会被释放(我最终会得到~50MB)。

我使用以下CoreData设置:

  • 一个masterContext PrivateQueueConcurrencyType
  • 一个mainContext MainQueueConcurrencyTypemasterContextparentContext
  • 导入在PrivateQueueConcurrencyTypemainContext parentContext的{​​{1}}
  • 上运行

以下方法开始导入:

func downloadProductImages(completion: (error: NSError?) -> Void) {
    if let moc = self.backgroundMOC {
        moc.performBlock { () -> Void in
            moc.reset()

            var err: NSError? = nil

            self.importBrandImages({ (error) -> Void in
                if error != nil {
                    completion(error: error)

                    return
                }

                moc.save(nil)

                self.importProductVariantThumbnails({ (error) -> Void in
                    if error != nil {
                        completion(error: error)

                        return
                    }

                    moc.save(nil)
                    moc.reset()

                    self.backgroundMOC = nil

                    completion(error: err)
                })
            })
        }
    }
}

这些方法下载图像并将其保存在数据库中:

private func importBrandImages(completion: (error: NSError?) -> Void) {
    if let moc = self.backgroundMOC {
        moc.performBlock { () -> Void in
            moc.reset()

            var error: NSError? = nil

            let brandsFetchReq = NSFetchRequest(entityName: "Brand")

            // brand images
            if let brands = moc.executeFetchRequest(brandsFetchReq, error: &error) as? [Brand] {

                let imageQueue = TaskQueue()

                autoreleasepool({ () -> () in
                    for brand in brands {
                        if let logoSrc = brand.logoSrc {
                            imageQueue.tasks +=~ { results, next in
                                ImageLoader.sharedLoader.imageForUrl(logoSrc.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!, completionHandler: { (image, url) -> () in
                                    if image != nil {
                                        brand.logo = UIImageJPEGRepresentation(image, 0.35)
                                    }

                                    next(nil)
                                })
                            }
                        }

                        if let bgImgSrc = brand.bgImageSrc {
                            imageQueue.tasks +=~ { results, next in
                                ImageLoader.sharedLoader.imageForUrl(bgImgSrc.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!, completionHandler: { (image, url) -> () in
                                    if image != nil {
                                        brand.bgImage = UIImageJPEGRepresentation(image, 0.35)
                                    }

                                    next(nil)
                                })
                            }
                        }
                    }
                })

                imageQueue.run(completion: { () -> Void in
                    moc.save(nil)

                    completion(error: error)
                })
            } else {
                completion(error: error)
            }
        }
    }
}

private func importProductVariantThumbnails(completion: (error: NSError?) -> Void) {
    var err: NSError? = nil

    if let moc = self.backgroundMOC {
        moc.performBlock { () -> Void in
            moc.reset()

            let pVariantsFetchReq = NSFetchRequest(entityName: "ProductVariant")

            if let variants = moc.executeFetchRequest(pVariantsFetchReq, error: &err) as? [ProductVariant] {
                let importQueue = TaskQueue()

                autoreleasepool({ () -> () in
                    for variant in variants {
                        if let thumbnailSrc = variant.thumbnailSrc {
                            importQueue.tasks +=~ { results, next in
                                ImageLoader.sharedLoader.imageForUrl(thumbnailSrc.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!, completionHandler: { (image, url) -> () in
                                    if image != nil {
                                        variant.thumbnail = UIImageJPEGRepresentation(image, 0.35)
                                    }

                                    next(nil)
                                })
                            }
                        }
                    }
                })

                importQueue.run { () -> Void in
                    moc.save(nil)

                    self.importProductVariantImages({ (error) -> Void in
                        completion(error: error)
                    })
                }
            }
        }
    }
}

private func importProductVariantImages(completion: (error: NSError?) -> Void) {
    var error: NSError? = nil

    if let moc = self.backgroundMOC {
        moc.performBlock { () -> Void in
            moc.reset()

            let pImagesFetchReq = NSFetchRequest(entityName: "ProductImage")

            // product images
            if let images = moc.executeFetchRequest(pImagesFetchReq, error: &error) as? [ProductImage] {
                let importQueue = TaskQueue()

                autoreleasepool({ () -> () in
                    for pImage in images {
                        if let imageSrc = pImage.imageSrc {
                            importQueue.tasks +=~ { results, next in
                                ImageLoader.sharedLoader.imageForUrl(imageSrc.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!, completionHandler: { (image, url) -> () in
                                    if image != nil {
                                        pImage.imageData = UIImageJPEGRepresentation(image, 0.35)
                                    }

                                    next(nil)
                                })
                            }
                        }
                    }
                })

                importQueue.run(completion: { () -> Void in
                    moc.save(nil)

                    completion(error: error)
                })
            } else {
                completion(error: error)
            }
        }
    }
}

我不知道,为什么没有释放内存。我使用Instruments来查找内存泄漏,但它没有显示任何内容。

1 个答案:

答案 0 :(得分:1)

您的问题似乎是ImageLoader包含缓存并且正在向其添加所有图像。如果您不需要该功能,并且它看起来并不像您那样,那么您应该将其删除并简化ImageLoader,以便下载并返回图像。