iOS 内存增加问题

Posted

技术标签:

【中文标题】iOS 内存增加问题【英文标题】:iOS Memory Increasing Issue 【发布时间】: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代码时,内存并没有增加。有人知道吗? 哦,已经这样做了,这是一大堆可变字符串,这就是我感到困惑的原因。应该在上面的帖子中说明这一点。 【参考方案1】:

找到解决方案here。

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

【讨论】:

以上是关于iOS 内存增加问题的主要内容,如果未能解决你的问题,请参考以下文章

iOS-关于缓存SDImageCacheImage,一直刷新UIImageView内存一直增加问题

iOS 内存使用量增加直到崩溃

iOS - UILabel(CALayer) - VMalloc 内存不断增加

在 iOS 中通过 HTTP 获取图像时内存分配不断增加

如何使用 Xcode 跟踪哪个项目增加了 iOS 中的内存?

实际内存不断增加 - 从视图中删除子视图 - iOS (ARC)