breno breno - 29 days ago 4
Swift Question

reducing memory consumption allocated by date core

I have a great difficulty is one week. I get a JSON with many objects and each object you can get up to 8 photos. I'm doing a test with a base of 15,000 objects put my memory consumption remains always almentanto until I receive the error

"Malloc error “can't allocate region” failed with error code 3"


How can I solve this? I tried to reset my core the context of the objects date but also not decided.

Below I put a part of my code:

for item in products {
i = i + 1
print(i)

let p = item as! NSDictionary
let product = NSEntityDescription.insertNewObjectForEntityForName("PRODUCT", inManagedObjectContext: self.context) as! PRODUCT

if tipo != "FULL"{
let chave = p["Chave"] as! String
if self.loadProductWithKey(chave).count > 0 {
self.deleteProductWithKey(chave)
}
}

product.chave = p["Chave"] as? String
product.chaveFabricante = p["ChaveFabricante"] as? String
product.chaveMarca = p["ChaveMarca"] as? String
product.chaveUnidade = p["ChaveUnidade"] as? String
product.chaveGrupo = p["ChaveGrupo"] as? String
product.codigo = p["Codigo"] as? String
product.codigoSegundario = p["CodigoSecundario"] as? String
product.descricaoNF = p["DescricaoNf"] as? String
product.descricaoDetalhada = p["DescricaoDetalhada"] as? String
product.chaveLicenca = p["ChaveLicenca"] as? String


var image = UIImage()
var url = NSURL()
var code = ""
var chave = ""
var fileName = ""

let photo1Url = p["UrlFoto1"] as! String
if photo1Url != ""{
url = NSURL(string: "\(_URLPREFIX)\(photo1Url)")!
if let foto = NSData(contentsOfURL: url) {
if foto.length > 0{
image = UIImage(data: foto)!
code = p["Codigo"] as! String
chave = p["Chave"] as! String
let documents = try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
fileName = "picture-\(chave)-\(code)-1.jpg"
let fileURL = documents.URLByAppendingPathComponent(fileName)
if let jpgImageData = UIImageJPEGRepresentation(image, 0.8) {
jpgImageData.writeToURL(fileURL, atomically: true)
}
product.urlFoto1 = fileName
}
}
}

let photo2Url = p["UrlFoto2"] as! String
if photo2Url != ""{
url = NSURL(string: "\(_URLPREFIX)\(photo2Url)")!
if let foto = NSData(contentsOfURL: url) {
if foto.length > 0{
image = UIImage(data: foto)!
code = p["Codigo"] as! String
chave = p["Chave"] as! String
let documents = try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
fileName = "picture-\(chave)-\(code)-2.jpg"
let fileURL = documents.URLByAppendingPathComponent(fileName)
if let jpgImageData = UIImageJPEGRepresentation(image, 0.8) {
jpgImageData.writeToURL(fileURL, atomically: true)
}
product.urlFoto2 = fileName
}
}
}

let photo3Url = p["UrlFoto3"] as! String
if photo3Url != ""{
url = NSURL(string: "\(_URLPREFIX)\(photo3Url)")!
if let foto = NSData(contentsOfURL: url) {
if foto.length > 0{
image = UIImage(data: foto)!
code = p["Codigo"] as! String
chave = p["Chave"] as! String
let documents = try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
fileName = "picture-\(chave)-\(code)-3.jpg"
let fileURL = documents.URLByAppendingPathComponent(fileName)
if let jpgImageData = UIImageJPEGRepresentation(image, 0.8) {
jpgImageData.writeToURL(fileURL, atomically: true)
}
product.urlFoto3 = fileName
}
}
}

let photo4Url = p["UrlFoto4"] as! String
if photo4Url != ""{
url = NSURL(string: "\(_URLPREFIX)\(photo4Url)")!
if let foto = NSData(contentsOfURL: url) {
if foto.length > 0{
image = UIImage(data: foto)!
code = p["Codigo"] as! String
chave = p["Chave"] as! String
let documents = try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
fileName = "picture-\(chave)-\(code)-4.jpg"
let fileURL = documents.URLByAppendingPathComponent(fileName)
if let jpgImageData = UIImageJPEGRepresentation(image, 0.8) {
jpgImageData.writeToURL(fileURL, atomically: true)
}
product.urlFoto4 = fileName
}
}
}

let photo5Url = p["UrlFoto5"] as! String
if photo5Url != ""{
url = NSURL(string: "\(_URLPREFIX)\(photo5Url)")!
if let foto = NSData(contentsOfURL: url) {
if foto.length > 0{
image = UIImage(data: foto)!
code = p["Codigo"] as! String
chave = p["Chave"] as! String
let documents = try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
fileName = "picture-\(chave)-\(code)-5.jpg"
let fileURL = documents.URLByAppendingPathComponent(fileName)
if let jpgImageData = UIImageJPEGRepresentation(image, 0.8) {
jpgImageData.writeToURL(fileURL, atomically: true)
}
product.urlFoto5 = fileName
}
}
}

do {
try self.context.save()
} catch {
print("============ erro nos produtos")

}
self.context.refreshAllObjects()
}

Answer

There are a number of things wrong with your code.

You should not use NSData(contentsOfURL:) to load data from a remote site. It freezes the main thread. Instead use NSURLSession. You can create a download task that will download your image data directly to files. It will do it asynchronously, which won't block the main thread.

You also shouldn't load large numbers of large objects in a loop without taking steps to avoid running out of memory. Enclose the part inside the loop that loads a large object with in an autoreleasepool block:

for (i, item) in products.enumerate() {
  autoreleasepool {
    //Put the body of your for loop here
  }
}

The autoreleasepool{} block tells the compiler that it should free temporary (or autoreleased) objects that were allocated inside the braces each time it exits the braces. (This is known as "draining the autorelease pool")

By putting an autoreleasepool{} block just inside your for loop, you release the autoreleased objects your code created on each pass through the loop.

However, if you use NSURLSession and a download task you won't have to worry about that. The system will download the files and save them automatically, and manage the memory for the process for you.

Comments