Ios 保存和获取核心数据需要高内存800MB和100%CPU/如何在swift4中批量插入和获取核心数据

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

我使用核心数据存储了10000-20000条记录。如果我试图保存和获取10000条记录,内存和cpu的消耗是巨大的,因为该应用程序在iPhone6plus和更早的设备上正在崩溃

以下是保存方法:----

下面是获取的方法:----

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()
}
}
}
核心数据结构如下所示:---

我对这些问题有太多困惑

  • 核心数据不适合存储20000条记录
  • 我是否需要刷新对象(对象,合并技术:bool)以获取海量数据 每次我都要像那样刷新对象
  • Instruments表示在let results= 尝试context.fetch(fetchrequest…..行为什么
  • 我是否需要批量保存和获取数据,这会增加应用程序的容量 性能和内存降低
  • 为什么CPU有时表示100%
  • 如果我在集合视图中显示10000条记录(从arrray加载数据) 导致任何问题??如果是,什么类型的问题
  • 需要你宝贵的建议和帮助使我变得完美吗

  • 您正在使用大量内存和CPU时间,因为:

    • 当您创建新的
      InboxData
      条目时,在保存更改之前,您需要为数组中的每个条目创建一个条目。您的代码意味着所有这些条目必须同时在内存中。如果您有数千个条目,则内存会很大
    • 当你获取条目时,你每次都会获取每个条目。同样,你的代码意味着你必须同时在内存中保存所有条目。同样,大量条目意味着大量内存。使用核心数据的一个主要原因是,几乎总是可以只将数据的一个子集而不是全部加载到内存中。哟你在装所有的东西
    • 您将一组属性从托管对象复制到字典中——因此现在内存中有两个而不是一个数据副本
    • 获取数据的代码对内存中的数据进行排序,以创建
      排序数据
      。您已经有大量对象加载到内存中;现在您正在做大量工作来对它们进行排序。这至少是将CPU固定为100%的部分原因
    • 在对数据进行排序后,您将结果分配给
      inboxTotalMailData
      displayTotalData
      ,这是在此函数之外定义的。这意味着即使此函数完成后,
      sortingdata
      中的所有数据仍保留在内存中
    一些有帮助的事情:

    • 保存数据时,请定期保存—每50个条目,或每100个条目,或任何能产生良好结果的数字。不要尝试创建数千个对象并将它们全部保存在内存中
    • 让fetch请求对数据进行排序,而不是先提取然后排序。fetch请求可以有排序描述符,而排序是由SQLite完成的。这将在CPU时间和内存使用方面更高效
    • 尽量避免一次获取所有内容,因为对于数千条记录,这意味着大量内存,而不管您做什么
    • 除非你有强烈的理由这样做,否则不要复制数据。你可以直接使用托管对象,像这样复制数据几乎是不合适的
    • 由于您使用的是集合视图,请考虑使用<代码> NSFetchedResultsController < /C>。它被设计为与表和集合视图一起工作,并有助于保持内存和CPU使用率下降。

    您使用了大量内存和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()
          }
          }
      
      }