繁体   English   中英

UITableView和NSFetchedResultsController的内存泄漏

[英]Memory leak with UITableView and NSFetchedResultsController

我有一个UITableView,其内容由NSFetchedResultsController获取CoreData管理。 我有两种类型的表视图单元格,一种带有图像,一种没有图像。 图像由UIDocument处理,并保留在iCloud普适文档容器中,并由客户端名称引用。

当屏幕上有许多用户生成的图像时,随着单元的生成和重新使用,我程序的内存使用率越来越高。 大约110 mb,我收到内存不足警告。

我怀疑tableView单元格中的prepareForReuse()方法未正确执行其工作。

这是我的UITableViewCell现在的样子:

class ClientTableViewCell: UITableViewCell {

@IBOutlet weak var clientName: UILabel!

@IBOutlet weak var clientModifiedDate: UILabel!

@IBOutlet weak var profileImage: UIImageView!

let dateFormatter = NSDateFormatter()

var document: MyDocument?
var documentURL: NSURL?
var ubiquityURL: NSURL?

var metaDataQuery: NSMetadataQuery?

var myClient : Client?
{
    didSet
    {
        updateClientInfo()
    }
}

override func prepareForReuse() {
    super.prepareForReuse()

    clientName.text = nil
    clientModifiedDate.text = nil

    if let mc = myClient
    {
        if mc.imageurl != ""
        {
            if let p = profileImage
            {
                p.image = nil
            } else
            {
                NSLog("nil document")
            }
        }
    } else
    {
         NSLog("nil client")
    }
}


func updateClientInfo()
{
    if myClient != nil
    {
        clientName.text = myClient!.name

        dateFormatter.dateStyle = .ShortStyle

        let dispDate = dateFormatter.stringFromDate(NSDate(timeIntervalSinceReferenceDate: myClient!.dateModified))

        clientModifiedDate.text = dispDate

        if let imageName = myClient?.imageurl  {

            if myClient?.imageurl != "" {

                var myClientName : String!

                myClientName = myClient!.name

                metaDataQuery = NSMetadataQuery()

                metaDataQuery?.predicate = NSPredicate(format: "%K like '\(myClientName).png'", NSMetadataItemFSNameKey)

                metaDataQuery?.searchScopes = [NSMetadataQueryUbiquitousDocumentsScope]

                NSNotificationCenter.defaultCenter().addObserver(self,
                    selector: "metadataQueryDidFinishGathering:",
                    name: NSMetadataQueryDidFinishGatheringNotification,
                    object: metaDataQuery!)

                metaDataQuery!.startQuery()

            }
        }
    }

}


func metadataQueryDidFinishGathering(notification: NSNotification) -> Void {

        let query: NSMetadataQuery = notification.object as! NSMetadataQuery

        query.disableUpdates()

        NSNotificationCenter.defaultCenter().removeObserver(self, name: NSMetadataQueryDidFinishGatheringNotification, object: query)

        query.stopQuery()

        let results = query.results

        if query.resultCount == 1 {
            let resultURL = results[0].valueForAttribute(NSMetadataItemURLKey) as! NSURL
                document = MyDocument(fileURL: resultURL)
                document?.openWithCompletionHandler({(success: Bool) -> Void in
            if success {

                if let pi = self.profileImage
                {
                    pi.image = self.document?.image
                }


                } else {
                    println("iCloud file open failed")
                }
            })

        }  else {
            NSLog("Could not find profile image, creating blank document")
        }
}

}

如果您不熟悉iCloud和UIDocument,您可能想知道为什么我要查询元数据以获取这些图像/文档。 如果您知道在无处不在的容器中提取这些图像/文档的可靠方法,我将不胜枚举。 这将导致在表视图单元格滚动期间这种弹出效果。

这是我填充单元格的函数:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    //set the client
    let client = clients.fetchedObjects![indexPath.row] as! Client

    //set the correct identifier
    if let imageurl = client.imageurl as String?
    {
        if imageurl == ""
        {
            var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifierNoImage, forIndexPath: indexPath) as? ClientTableViewCell
            cell!.myClient = client
            return cell!

        } else
        {
            var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as? ClientTableViewCell
            cell!.myClient = client
            return cell!
        }
    }
    var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifierNoImage, forIndexPath: indexPath) as? ClientTableViewCell
    cell!.myClient = client
    return cell!
}

我本来打算使用属性imageurl来存储客户端配置文件图像的名称和url,但是由于无处不在的容器url对于每个设备都是唯一的,因此我现在仅使用它来检测此客户端是否有图像。 。

我已经有几个星期了,这个问题似乎无法确定。 任何指导将不胜感激!

工作台:Xcode 6.3和Swift 1.2。

解决了我自己的内存泄漏! 在这里有了这个答案的帮助:[ UIDocument从不调用dealloc

我正在查询UIDocuments,并且从未关闭过它们。 这就是ARC无法清除我未使用的UIDocuments的原因。 上面的链接具有Object C版本,但是对于使用Swift的人,请在使用它们后尝试以下这些行来关闭文档:

document?.updateChangeCount(UIDocumentChangeKind.Done)
document?.closeWithCompletionHandler(nil)

呼! 很高兴那烂摊子已经过去了。 希望这对某人有帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM