ios - 保存和获取在核心数据中消耗高内存 800MB 和 100% CPU/如何在 swift4 中批量插入和获取核心数据

标签 ios swift xcode core-data memory-leaks

我使用核心数据存储了 10000-20000 条记录。如果我尝试保存和获取 10000 条记录,内存和 CPU 消耗很大,因为该应用程序在 iphone 6 plus 和更早的设备中崩溃。

pic continuously increses upto 800mb for 10000 records

保存方法如下:----

   //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()
    }
    }

}

核心数据结构是这样的:::---

enter image description here

我对这些有太多困惑的问题。

  1. 核心数据不适合存储 20000 条记录??
  2. 我需要为大数据刷新对象(对象,mergeChnage:bool)吗 每次我必须像那样刷新对象。
  3. 仪器指示在 let results = 处获取结果时发生内存泄漏 尝试 context.fetch(fetchrequest.....行为什么??
  4. 我是否需要批量保存和获取数据会增加应用程序 性能和内存减少??
  5. 为什么 CPU 有时显示 100% ??
  6. 如果我在 Collection View 中显示 10000 条记录(从 arrray 加载数据) 导致任何问题?如果是,什么样的问题??
  7. 需要您的宝贵建议和帮助让我变得完美????

最佳答案

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

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

一些有用的东西:

  • 保存数据时,请定期保存——每 50 个条目,或每 100 个条目,或任何能产生良好结果的数字。 不要尝试创建数千个对象并将它们全部保存在内存中。
  • 让获取请求对数据进行排序,而不是先获取然后再排序。获取请求可以有排序描述符,排序由 SQLite 完成。这将大大提高 CPU 时间和内存使用效率。
  • 尽量避免一次获取所有内容,因为成千上万的记录意味着大量内存,无论您做什么。
  • 不要复制数据,除非您有一些非常令人信服的理由这样做。您可以直接使用托管对象,像这样复制数据几乎是不合适的。
  • 由于您似乎在使用 Collection View ,请考虑使用 NSFetchedResultsController。它旨在与表和 Collection View 一起使用,并有助于降低内存和 CPU 使用率。

关于ios - 保存和获取在核心数据中消耗高内存 800MB 和 100% CPU/如何在 swift4 中批量插入和获取核心数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49276426/

相关文章:

ios - Swift 是否可以继承一个轻量级的通用 Objective-c 类?

ios - 无法快速使用 Protocol 扩展 ObjC 类

swift - 子类节点,但想检测场景中的触摸

swift - 如何在 Swift 4 中搜索字符串中的子字符串?

swift - 在 AVAudioPlayer 中播放音调时如何在循环之间添加延迟?

ios - 带部分的动态 TableView

ios - 我是否需要增量获取 CloudKit 更改和订阅?

ios - 5星级评级系统数据库设计

ios - 在另一个 swift 类中使用 String

ios - Xcode错误无效的图像路径-CFBundleIconFiles 144x144、152x152、76x76和120x120