【问题标题】:iOS Memory Increasing IssueiOS 内存增加问题
【发布时间】:2015-01-07 20:55:02
【问题描述】:

我正在 iOS 的后台线程上提交构建的 JSON 数据,在运行时,我看到这里的内存呈指数增长,最终导致崩溃。我已经多次浏览了这段代码,只是无法弄清楚为什么内存会增加,因为在每次迭代期间似乎所有内容都会被释放。

它的作用是从 Core Data 中实现的队列中提取记录,并为其中的每 32 个记录提交一个 HTTP PUT 请求到带有该数据的服务器。在每次迭代之后,它会删除这些记录并保存上下文。

编辑:经过测试,我发现它是其中的 HTTP 部分。我仍然无法说出是什么导致了这种情况并迫使更多的内存。可能有太多单独的连接?

代码如下:

class func startSubmitting()
{
    // If this has already been called then don't go back into it
    if submitThreadRunning
    {
        return
    }

    var mainQueue:NSOperationQueue = NSOperationQueue()

    mainQueue.addOperationWithBlock(
    {
        let url: String = "URL_HERE"

        let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        let managedContext = NSManagedObjectContext()
        managedContext.persistentStoreCoordinator = appDelegate.persistentStoreCoordinator

        submitThreadRunning = true

        var offSetCount = 0

        var fetchRequest = NSFetchRequest(entityName:"Queue")
        var error: NSError?

        var sortDescriptor = NSSortDescriptor(key: "timestamp", ascending: false)
        fetchRequest.sortDescriptors?.append(sortDescriptor)

        // Limit to 32 records at a time
        fetchRequest.fetchLimit = 32
        fetchRequest.fetchOffset = offSetCount

        while submitThreadRunning
        {
            if let fetchedResults = managedContext.executeFetchRequest(fetchRequest, error: &error) as? [Queue]
            {
                // If no fetched results, sleep for a bit so as to not hammer the battery life
                if fetchedResults.count == 0
                {
                    NSThread.sleepForTimeInterval(5.0)
                    continue
                }

                var counter = 0
                var data = String(format:"{\"apiKey\": \"%@\", \"data\":[", apiKey!)

                for result in fetchedResults
                {
                    if submitThreadRunning
                    {
                        let count = fetchedResults.count

                        if fetchedResults.count != (counter + 1)
                        {
                            data += result.json + ","

                            // Remove the record
                            managedContext.deleteObject(result)

                            // Update the counter
                            counter++

                            // Update the offset
                            offSetCount++

                            continue
                        }
                        else
                        {
                            data += result.json + "]}"
                        }
                    }
                    else
                    {
                        // We are stopping so go ahead and finish off the array and continue
                        data += result.json + "]}"
                    }

                    var request: NSMutableURLRequest = NSMutableURLRequest()
                    var response: NSURLResponse?

                    request.URL = NSURL(string: url)
                    request.HTTPMethod = "PUT"
                    request.setValue("application/json", forHTTPHeaderField: "Accept")
                    request.setValue("application/json", forHTTPHeaderField: "Content-Type")

                    request.HTTPBody = (data as NSString).dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: true)

                    NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)

                    let statusCode = (response as NSHTTPURLResponse).statusCode

                    // Handle any errors
                    if error != nil || statusCode >= 400
                    {
                        // Undo all changes to the data store from this iteration
                        for var i = 0; i < counter - 1; i++
                        {
                            managedContext.undo()
                        }

                        // Update the offest
                        offSetCount++

                        continue
                    }

                    // Remove the record
                    managedContext.deleteObject(result)

                    // Update the offest
                    offSetCount++
                }
            }

            // Save all changes to the data store
            managedContext.save(&error)

            if error != nil
            {
                // TODO Show an error message on the UI Thread
            }
        }
    })
}

【问题讨论】:

  • “重现的最短代码”是关闭原因的相关位。请将其缩减为具有相同问题的较小程序。
  • 你确定errornil
  • 使用工具,卢克。
  • 经过进一步测试,我发现当我取出HTTP代码时,内存并没有增加。有人知道吗?
  • 哦,已经这样做了,这是一大堆可变字符串,这就是我感到困惑的原因。应该在上面的帖子中说明这一点。

标签: ios http core-data swift memory-management


【解决方案1】:

找到解决方案here

它为所有 HTTP 请求和响应创建了一个非常大的缓存,这就是 Instruments 显示已创建的 6K+ 字符串的原因。因此,一旦我输入那行代码,它就可以正常工作,并且不再存在内存问题。这似乎是 iOS 在幕后所做的事情,并且在 API 文档中没有很好地记录。所以希望这对其他人有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多