中断托管对象和集合视图单元格之间的强引用循环



更新 :

与Core Data或CollectionView无关。我从未解雇过持有 CollectionView 的 ViewController 。更多在下面的答案中!


我在 Swift iOS 中遇到内存泄漏。首先我认为它位于我的获取函数中,但后来我尝试了一些不同的东西。我切断了我的UICollectionViewCell和我在各个地方的Managed Object之间的联系。我正在获取图像。因此,我将获取的结果替换为随机图像资产,该资产被添加到数组中,其次数与结果一样多。这总是修复我的泄漏。所以现在我知道这不是我的获取函数的问题,在通往 Cell 的路上的任何其他函数。

经过一番谷歌搜索,我发现Core Data倾向于自己创建强大的参考周期。但我不认为就是这样。如果是,我不在 Cell 中使用生成的图像数组应该没关系。我应该仍然有泄漏,但是当我没有将核心数据中的图像连接到单元时,我没有泄漏。

我不明白的是为什么我首先会泄漏。我认为数组的工作方式类似于值,而不是引用。因此,将从核心数据加载的图像放在数组中应该像副本一样工作,并且不应该有任何强大的参考周期......

我还发现,刷新具有图像的二进制数据贡品的托管对象并不能解决问题。

那我现在该怎么办?我需要删除所有单元格吗?我是否需要从核心数据中从 NSData 中制作 UIImages(浏览了一些说字符串像值但 NSStrings 不工作的东西,所以也许 NSData 的东西就像一个参考)?我需要找到一种方法来刷新对象的属性吗?...

谢谢!

获取(也尝试将内容设置为 weak ,不起作用):

    import UIKit
    import CoreData

    func getFilteredThumbImages (albumIdentifier: String, moc : NSManagedObjectContext?) -> [NSData]? {
        var error: NSError?
        let resultPredicate = NSPredicate(format: "iD = %@", albumIdentifier)
        let albumfetchRequest = NSFetchRequest(entityName: "Album")
        albumfetchRequest.predicate = resultPredicate
        var results = moc!.executeFetchRequest(albumfetchRequest, error:&error)!
        if error == nil {
            weak var tempFThumbs = results.last!.mutableSetValueForKey("filteredThumbs")
            weak var testFoundImages = tempFThumbs!.mutableSetValueForKey("imageData")
            var foundImages = testFoundImages!.allObjects as [NSData]
            moc!.refreshObject(results.last! as NSManagedObject, mergeChanges: false)
            moc!.reset()
           return foundImages
        }
        else {
            moc!.refreshObject(results.last! as NSManagedObject, mergeChanges: false)
            //appDel?.managedObjectContext?.reset()
            moc!.reset()
            return nil
        }
    }

UICollectionViewCell :

import UIKit
class CollectionViewCell: UICollectionViewCell {

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    let textLabel: UILabel!
    let imageView: UIImageView!
    override init(frame: CGRect) {
        NSLog("MyObject init")
        super.init(frame: frame)
        imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height))
        imageView.backgroundColor = UIColor(red:1, green:0.992, blue:0.965, alpha:1)
        imageView.contentMode = UIViewContentMode.ScaleAspectFit
        imageView.clipsToBounds = true
        contentView.backgroundColor = UIColor(red:1, green:0.992, blue:0.965, alpha:1)
        contentView.addSubview(imageView)
    }
}

在单元格中输入图像(拇指是一个变量数组 => [NSData]):

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        println("loading...")
        weak var cell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionViewCell", forIndexPath: indexPath) as? CollectionViewCell
        //cell!.imageView?.image = UIImage(named: "test")

        if thumbs != nil {
            cell!.imageView?.image = UIImage(data: thumbs![indexPath.row])
            println("loading (thumbs!.count) cells")
        }


        return cell!
    }

问题是你的故事板中有一个循环。您正在从视图控制器 A 推送到视图控制器 B,然后从视图控制器 B "返回"到视图控制器 A。以此类推,每次。因此,您的导航控制器只是堆积了相同视图控制器的大量副本。所以你最终会得到所有这些图像的大量副本。

当你做这种事情时,你没有得到通知总是让我感到惊讶。这是一个经典的错误,而且很容易犯。当然,界面生成器可以检测到这种循环并警告您。但它没有...

相关内容

  • 没有找到相关文章

最新更新