2016-10-03 12 views
0

Ich verwende Core Data zum ersten Mal in meinem Projekt und ich habe das Gefühl, dass es ein ernsthaftes Problem in meinem Ansatz gibt. Was ich mache ist, dass ich Daten vom Server abrufe (Daten enthalten auch PNGs). Speichern Sie es in den Stammdaten lokal. Beim Laden der App lade ich dann die gesamten Daten in ein Array. Dann wird dieses Array verwendet, wo immer ich es brauche. Ich denke, ich folge einem sehr schlechten Ansatz. Kann mir jemand sagen, was ein besserer Ansatz sein sollte? Soll ich Core Data nur dann abfragen, wenn Daten benötigt werden, anstatt alles beim Start zu laden?Core Data Memory Crash

Wenn Daten in das Array gefüllt werden, kann ich sehen, dass der Speicher in Xcode ansteigt und nach einem bestimmten Wert abstürzt.

Hier ist mein Code für das Speichern von Daten:

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)") 
    } 
} 

wo menuItems ein Dictionary ist, die sowohl Text als auch PNG-Bilder enthält. Außerdem enthalten deals und foodPlacePhotos nur PNG-Bilder. Hier

ist der Code für fetching:

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)") 
    } 
} 

und hier ist der Code zum Löschen Daten:

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)") 
    } 
} 
+0

Versuchen Sie, Core Data Multithreading zu verwenden. Bitte gehen Sie durch https://code.utsplus.com/tutorials/core-data-and-swift-concurrency--cms-25118 –

+0

Vielen Dank für Ihre Antwort, aber ich glaube nicht, dass dies mein Problem ist. Ich habe Speicherproblem, dass es zu viel Speicher nimmt und abstürzt, weil es aus dem Speicher kommt. Ich kann sehen, dass das Gedächtnis ansteigt und ab einer bestimmten Grenze stürzt es ab. – kashif789us

+0

Was ist Datenmenge? Ich habe Probleme mit dem Speicher, dann ist es auch ein Teil des Thread-Managements. Übrigens schauen Sie in diese https://github.com/mmorey/MDMHPCoreData https://www.youtube.com/watch?v=O7C6euzQt-o –

Antwort

1

schwierig, ohne viel mehr Details über Ihren Code normativ zu sein. Aber ein paar Gedanken: Anstatt die PNG-Daten in CoreData selbst zu speichern, erwägen Sie, sie direkt im Dateisystem zu speichern und CoreData zu verwenden, um nur den Dateinamen für das PNG zu speichern.

  • Wenn Sie die PNGs in CoreData wirklich möchten, können Sie auch eine separate Entität für das PNG hinzufügen und Ihrer aktuellen Entität eine neue Beziehung hinzufügen.
  • Entweder wird verhindert, dass alle PNG-Daten in den Speicher geladen werden, wenn Sie das Array laden. Sie können dann die PNGs (entweder vom Dateisystem oder von der zugehörigen Entität) nach Bedarf laden/entladen.

    Darüber hinaus prüfen, mit:

    Diese helfen alle Objekte zu vermeiden, in den Speicher geladen wird.

    +0

    Ich habe den Code hinzugefügt. – kashif789us