Memory Problems with UIImage(contentsOfFile)

2019-09-09 14:21发布

问题:

I have a Collection View where i load some Images from my documents directory:

func reloadNotesFromStore() {
    {

        let fetchRequest = NSFetchRequest(entityName: "TaskDraw")

        let formsPredicate = NSPredicate(format: "task_id = %@", self.task_id)
        fetchRequest.predicate = formsPredicate

        let sortDescriptor = NSSortDescriptor(key: "createdAt", ascending: false)
        let sortDescriptors = [sortDescriptor]
        fetchRequest.sortDescriptors = sortDescriptors

        self.photos.removeAll(keepCapacity: false)

        let taskDrawings = (try! context.executeFetchRequest(fetchRequest)) as! [TaskDraw]

        let path = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as NSURL

        for taskDraw in taskDrawings {

            let imageFilename = "\(taskDraw.remoteID!)_combined.png"
            let imageFullPath = path.URLByAppendingPathComponent("\(self.task_id)/\(imageFilename)")

            // create combined image to display
            let photo = Photo(image: UIImage(contentsOfFile: imageFullPath.path!)!)

            photo.selected = false
            photo.taskDraw = taskDraw

            self.photos.append(photo)
        }

        } ~> {
            self.collectionView?.reloadData()
    }

}

Every time when ill display my CollectionViewController, my Memory usage increases by about 30 MB.

The images that i load with UIImage(contentsOfFile) are about 150 kb.

Ok tried no Leos Solution, but still no success. When ill reload my Controller (modally) my memory always increases about 30-40 Mbytes.

func reloadNotesFromStore() {
    {

        let fetchRequest = NSFetchRequest(entityName: "TaskDraw")

        let formsPredicate = NSPredicate(format: "task_id = %@", self.task_id)
        fetchRequest.predicate = formsPredicate

        let sortDescriptor = NSSortDescriptor(key: "createdAt", ascending: false)
        let sortDescriptors = [sortDescriptor]
        fetchRequest.sortDescriptors = sortDescriptors

        self.items.removeAll(keepCapacity: false)

        let taskDrawings = (try! context.executeFetchRequest(fetchRequest)) as! [TaskDraw]

        let path = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as NSURL

        for taskDraw in taskDrawings {

            let imageFilename = "\(taskDraw.remoteID!)_combined.png"
            let imageFullPath = path.URLByAppendingPathComponent("\(self.task_id)/\(imageFilename)")

            // create combined image to display
            let collectionViewItem = CollectionViewItem()
            collectionViewItem.filePath = imageFullPath
            collectionViewItem.selected = false
            collectionViewItem.taskDraw = taskDraw

            self.items.append(collectionViewItem)
        }

        } ~> {
            self.collectionView?.reloadData()
    }

}

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("PhotoCell", forIndexPath: indexPath) as! PhotoCell

    let item = items[indexPath.item]

    cell.imageView.image = UIImage(contentsOfFile: item.filePath!.path!)!
    .....

How can i force Swift to release my memory? Update2:

When ill use UIImage(named: ..) instead of UIImage(contentsOfFile: ....) then on first init the memory increase by about 40 Mbyte, but stays when ill dismiss the View and load it again (i guess this happens because named: .. caches the image)

But this also do not release the memory when ill dismiss the VC.

回答1:

Ok i fixed the problem now with the following solution:

I still create an UIImage in Memory, like this:

for taskDraw in taskDrawings {

       let imageFilename = "\(taskDraw.remoteID!)_combined.png"
       let imageFullPath = path.URLByAppendingPathComponent("\(self.task_id)/\(imageFilename)")

       let photo = Photo(image: UIImage(contentsOfFile: imageFullPath.path!)!.resizeToWidth(300))
       photo.taskDraw = taskDraw
       photo.addNote = false
       self.photos.append(photo)

So only show the resized image in the CollectionView. (Otherwise i need to store a Thumbnail on Disk)

And:

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    self.photos.removeAll(keepCapacity: false)
}

In Controller.

Now, the Memory consumption is quite lower AND after dismissing my ViewController, the used memory is now released.



回答2:

I have a image in Document directory , I am using UIImage(contentsOfFile:) method to make the UIImage, image exist in DocumentDirectory but method return nil.

  let img = UIImage(contentsOfFile: ChatUtils.getPathWithFolderName(kChatAttachmentOriginalFolderName) + ("/" + fileName))