核心数据内存崩溃
问题描述:
我在我的项目中第一次使用核心数据,我觉得在我的方法中存在一个严重的问题。我所做的是我从服务器获取数据(数据也包括png)。将其保存在本地的核心数据中。然后在应用程序启动时,我将整个数据加载到一个数组中。然后这个数组用在我需要的地方。我认为我正在采取一种非常糟糕的做法。任何人都可以指导我什么应该是一个更好的方法?我应该只在需要数据时才查询核心数据,而不是在开始时将所有内容加载到内存中?核心数据内存崩溃
当数据被填充到数组中时,我可以看到Xcode中的内存增加,并且在某个值之后,它崩溃了。
这是我保存数据代码:
func saveDataLocally() {
let moContext = ((UIApplication.shared.delegate) as! AppDelegate).managedObjectContext
let entity = NSEntityDescription.entity(forEntityName: "FoodPlace", in: moContext)
for foodPlaceData in self.downloadedData_ {
let foodPlace = NSManagedObject(entity: entity!, insertInto: moContext) as! FoodPlace
foodPlace.objectId = foodPlaceData.objectId_
foodPlace.name = foodPlaceData.name_
foodPlace.address = foodPlaceData.address_
foodPlace.keywords = foodPlaceData.keywords_
foodPlace.baseFavourites = Int64(foodPlaceData.baseFavourites_)
foodPlace.startingTime = foodPlaceData.startingTime_
foodPlace.endingTime = foodPlaceData.endingTime_
foodPlace.category = foodPlaceData.category_
foodPlace.basePrice = foodPlaceData.basePrice_
foodPlace.dealTitle = foodPlaceData.dealTitle_
foodPlace.versionNumber = Int64(foodPlaceData.versionNumber_)
foodPlace.menuItems = NSKeyedArchiver.archivedData(withRootObject: foodPlaceData.menuItems_)
foodPlace.location = NSKeyedArchiver.archivedData(withRootObject: foodPlaceData.location_)
foodPlace.deals = NSKeyedArchiver.archivedData(withRootObject: foodPlaceData.deals_)
foodPlace.foodPlacePhotos = NSKeyedArchiver.archivedData(withRootObject: foodPlaceData.foodPlacePhotos_)
moContext.insert(foodPlace)
}
do {
try moContext.save()
}
catch let error {
print("error saving = \(error.localizedDescription)")
}
}
其中menuItems
是Dictionary
包含文本和PNG图像。另外,deals
和foodPlacePhotos
只包含png图像。
这里是抓取代码:
func loadDataLocally() {
let moContext = ((UIApplication.shared.delegate) as! AppDelegate).managedObjectContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "FoodPlace")
do {
let results = try moContext.fetch(request)
let savedFoodPlaceData = results as! [FoodPlace]
downloadedData_ = []
for foodPlace in savedFoodPlaceData {
let objectId = foodPlace.objectId
let name = foodPlace.name
let address = foodPlace.address
let keywords = foodPlace.keywords
let baseFavourites = foodPlace.baseFavourites
let startingTime = foodPlace.startingTime
let endingTime = foodPlace.endingTime
let category = foodPlace.category
let menuItems = NSKeyedUnarchiver.unarchiveObject(with: foodPlace.menuItems!) as? [Dictionary<String,AnyObject>]
let location = NSKeyedUnarchiver.unarchiveObject(with: foodPlace.location!) as? Dictionary<String,Double>
let deals = NSKeyedUnarchiver.unarchiveObject(with: foodPlace.deals!) as? [UIImage]
let basePrice = Float(foodPlace.basePrice)
let dealTitle = foodPlace.dealTitle
let versionNumber = foodPlace.versionNumber
let foodPlacePhotos = NSKeyedUnarchiver.unarchiveObject(with: foodPlace.foodPlacePhotos!) as? [UIImage]
let data = FoodPlaceData(objectId: objectId!, name: name!, address: address!, category: category!, keywords: keywords!, baseFavourites: Int(baseFavourites), startingTime: startingTime!, endingTime: endingTime!, menuItems: menuItems!, location: location!, deals: deals!,basePrice: basePrice,dealTitle: dealTitle!,versionNumber: Int(versionNumber),foodPlacePhotos: foodPlacePhotos!)
downloadedData_.insert(data, at: downloadedData_.count)
}
}
catch let error {
print("error fetching = \(error.localizedDescription)")
}
}
,这里是删除数据的代码:
func deleteAllLocalData() {
let moContext = ((UIApplication.shared.delegate) as! AppDelegate).managedObjectContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "FoodPlace")
fetchRequest.returnsObjectsAsFaults = false
do {
let results = try moContext.fetch(fetchRequest)
for managedObject in results {
let managedObjectData : NSManagedObject = managedObject as! NSManagedObject
moContext.delete(managedObjectData)
}
try moContext.save()
} catch let error {
print("Delete all data in FoodPlace error : \(error) \((error as NSError).userInfo)")
}
}
答
难没有关于你的代码了很多更详细地规定。但有一些想法:
- 而不是将PNG数据存储在CoreData本身中,可以考虑将其直接存储在文件系统中,并使用CoreData仅存储PNG的文件名。
- 或者,如果您确实需要CoreData中的PNG,请考虑为PNG添加一个单独的实体,并添加一个从当前实体到新实体的一对一关系。
以上任何一种都会避免在加载阵列时将所有PNG数据加载到内存中。然后,您可以根据需要加载/卸载PNG(从文件系统或相关实体)。
此外,可以考虑使用:
这将有助于避免所有对象被加载到内存中。
+0
我已经添加了代码。 – kashif789us
尝试使用核心数据多线程。请通过https://code.tutsplus.com/tutorials/core-data-and-swift-concurrency--cms-25118 –
谢谢你的回复,但我不认为这是我的问题。我有内存问题,它会占用太多的内存并因为内存不足而崩溃。我可以看到内存增加,超出一定的限制,它崩溃。 – kashif789us
什么是数据量?我正面临内存问题,那么它也是线程管理的一部分。顺便看看这些https://github.com/mmorey/MDMHPCoreData https://www.youtube.com/watch?v=O7C6euzQt-o –