Ios 保存和获取核心数据需要高内存800MB和100%CPU/如何在swift4中批量插入和获取核心数据
我使用核心数据存储了10000-20000条记录。如果我试图保存和获取10000条记录,内存和cpu的消耗是巨大的,因为该应用程序在iPhone6plus和更早的设备上正在崩溃 以下是保存方法:---- 下面是获取的方法:----Ios 保存和获取核心数据需要高内存800MB和100%CPU/如何在swift4中批量插入和获取核心数据,ios,swift,xcode,core-data,memory-leaks,Ios,Swift,Xcode,Core Data,Memory Leaks,我使用核心数据存储了10000-20000条记录。如果我试图保存和获取10000条记录,内存和cpu的消耗是巨大的,因为该应用程序在iPhone6plus和更早的设备上正在崩溃 以下是保存方法:---- 下面是获取的方法:---- strongSelf.inboxDataFromCoreData(fetchLimit:0)//调用viewdidload的方法 //标记:-从Coredata获取inboxData func inboxDataFromCoreData(fetchLimit:Int
strongSelf.inboxDataFromCoreData(fetchLimit:0)//调用viewdidload的方法
//标记:-从Coredata获取inboxData
func inboxDataFromCoreData(fetchLimit:Int)
{
var inboxCoredataFetch=[[String:AnyObject]]()
让context=CoreDataStack.sharedInstance.persistentContainer.viewContext
let fetchRequest=NSFetchRequest(entityName:String(description:InboxData.self))
做{
fetchRequest.sortDescriptors=[NSSortDescriptor(键:“日期”,升序:false)]
fetchRequest.fetchLimit=fetchLimit
let results=try context.fetch(fetchRequest)as![InboxData]
打印(“收件箱\核心数据:\(results.count)”)
查询结果中的数据
{
让发件人=data.sender
让mailPath=data.mailPath
让fileType=data.fileType
设fullMail=data.fullMail
让attachmentName=data.attachmentName
设size=data.size
让日期=data.date
设dateForsearch=data.dateForsearch
让inboxMail=data.inboxMail
inboxCoredataFetch.append([“发件人”:发件人作为任何对象,“MailPath”:MailPath!作为任何对象,“文件类型”:文件类型作为任何对象,“FullMail”:FullMail作为任何对象,“AttachmentName”:AttachmentName作为任何对象,“Size”:大小作为任何对象,“Date”:日期作为任何对象,“DateForSearch”:DateForSearch作为任何对象,“InboxMail”:InboxMail作为任何对象])
}
}
以讹传讹{
打印(错误描述)
}
var sortingdata=inboxCoredataFetch作为数组
让mailBoxSortDescriptor=NSSortDescriptor(键:“日期”,升序:false,选择器:nil)
让dateDescriptor=NSSortDescriptor(键:“AttachmentName”,升序:true,选择器:#选择器(NSString.caseInsensitiveCompare))
sortingdata=((将数据排序为NSArray)。将Darray(使用:[mailBoxSortDescriptor,dateDescriptor])排序为![[String:AnyObject]]
inboxTotalMailData=排序数据
如果appDataLoadingFirst==true
{
appDataLoadingFirst=false
displayTotalData=排序数据
DispatchQueue.main.async{
self.hideActivityIndicator()
self.collectionView.reloadData()
}
}
}
核心数据结构如下所示:---
我对这些问题有太多困惑
您正在使用大量内存和CPU时间,因为:
- 当您创建新的
条目时,在保存更改之前,您需要为数组中的每个条目创建一个条目。您的代码意味着所有这些条目必须同时在内存中。如果您有数千个条目,则内存会很大InboxData
- 当你获取条目时,你每次都会获取每个条目。同样,你的代码意味着你必须同时在内存中保存所有条目。同样,大量条目意味着大量内存。使用核心数据的一个主要原因是,几乎总是可以只将数据的一个子集而不是全部加载到内存中。哟你在装所有的东西
- 您将一组属性从托管对象复制到字典中——因此现在内存中有两个而不是一个数据副本
- 获取数据的代码对内存中的数据进行排序,以创建
。您已经有大量对象加载到内存中;现在您正在做大量工作来对它们进行排序。这至少是将CPU固定为100%的部分原因排序数据
- 在对数据进行排序后,您将结果分配给
和inboxTotalMailData
,这是在此函数之外定义的。这意味着即使此函数完成后,displayTotalData
中的所有数据仍保留在内存中sortingdata
- 保存数据时,请定期保存—每50个条目,或每100个条目,或任何能产生良好结果的数字。不要尝试创建数千个对象并将它们全部保存在内存中
- 让fetch请求对数据进行排序,而不是先提取然后排序。fetch请求可以有排序描述符,而排序是由SQLite完成的。这将在CPU时间和内存使用方面更高效
- 尽量避免一次获取所有内容,因为对于数千条记录,这意味着大量内存,而不管您做什么
- 除非你有强烈的理由这样做,否则不要复制数据。你可以直接使用托管对象,像这样复制数据几乎是不合适的
- 由于您使用的是集合视图,请考虑使用<代码> NSFetchedResultsController < /C>。它被设计为与表和集合视图一起工作,并有助于保持内存和CPU使用率下降。
- 创建新的
收件箱数据时
//InboxCoredata Saving Method i..(calling saving method ii) func InboxSaveInCoreDataWith(array: [[String: AnyObject]]) { _ = array.map{self.InboxCreateCollectionEntityFrom(dictionary: $0)} do { try CoreDataStack.sharedInstance.persistentContainer.viewContext.save() print("Inbox Data saved Sucessfully in Coredata ") } catch let error { print(error) } } // Inbox Coredata saving method ii func InboxCreateCollectionEntityFrom(dictionary: [String: AnyObject]) -> NSManagedObject? { let context = CoreDataStack.sharedInstance.persistentContainer.viewContext if let inboxEntity = NSEntityDescription.insertNewObject(forEntityName: "InboxData", into: context) as? InboxData { inboxEntity.fileType = dictionary["FileType"] as? String inboxEntity.sender = dictionary["Sender"] as? String inboxEntity.mailPath = dictionary["MailPath"] as? String inboxEntity.fullMail = dictionary["FullMail"] as? NSObject inboxEntity.attachmentName = dictionary["AttachmentName"] as? String inboxEntity.size = dictionary["Size"] as! Int32 inboxEntity.date = dictionary["Date"] as? NSDate inboxEntity.dateForSearch = dictionary["DateForSearch"] as? String inboxEntity.inboxMail = dictionary["InboxMail"] as? String return inboxEntity } return nil }
strongSelf.inboxDataFromCoreData(fetchLimit: 0) // Methods calling in viewdidload //MARK: - Fetching inboxData from Coredata func inboxDataFromCoreData(fetchLimit :Int) { var inboxCoredataFetch = [[String : AnyObject]]() let context = CoreDataStack.sharedInstance.persistentContainer.viewContext let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: String(describing: InboxData.self)) do { fetchRequest.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)] fetchRequest.fetchLimit = fetchLimit let results = try context.fetch(fetchRequest) as! [InboxData] print("inbox_coredata:\(results .count)") for data in results { let sender = data.sender let mailPath = data.mailPath let fileType = data.fileType let fullMail = data.fullMail let attachmentName = data.attachmentName let size = data.size let date = data.date let dateForsearch = data.dateForSearch let inboxMail = data.inboxMail inboxCoredataFetch.append(["Sender" : sender as AnyObject,"MailPath": mailPath! as AnyObject, "FileType":fileType as AnyObject, "FullMail":fullMail as AnyObject, "AttachmentName": attachmentName as AnyObject, "Size":size as AnyObject,"Date": date as AnyObject,"DateForSearch" :dateForsearch as AnyObject,"InboxMail":inboxMail as AnyObject]) } } catch let err as NSError { print(err.debugDescription) } var sortingdata = inboxCoredataFetch as Array let mailBoxSortDescriptor = NSSortDescriptor(key: "Date", ascending:false, selector: nil) let dateDescriptor = NSSortDescriptor(key: "AttachmentName", ascending: true, selector: #selector(NSString.caseInsensitiveCompare)) sortingdata = ((sortingdata as NSArray).sortedArray(using: [ mailBoxSortDescriptor,dateDescriptor]) ) as! [[String : AnyObject]] inboxTotalMailData = sortingdata if appDataLoadingFirst == true { appDataLoadingFirst = false displayTotalData = sortingdata DispatchQueue.main.async { self.hideActivityIndicator() self.collectionView.reloadData() } } }