2017-04-17 4 views
0

Je rencontre ce problème de performance énorme tout en enregistrant NSAttrbutedString avec des images dans Core Data.Ajouter des images dans NSAttributedString et enregistrer dans Core Data performance

CoreData Schema

Il y a un UITextView où permet à l'utilisateur de saisir du texte, ainsi que l'ajout d'images. Lorsque l'utilisateur a fini de taper et de cliquer sur le bouton 'done', il sera enregistré dans CoreData et affiché dans un TableView.

Voici comment j'enregistrer le contenu lorsque cliquez sur « fait » le bouton:

Créer un MOC privé et affecter le AppDelegates managedObjectContext comme MOC mère.

privateMOC = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType) 
privateMOC.parent = managedObjectContext 

privateMOC.perform { 
    do { 
     try self.privateMOC.save() 

     self.managedObjectContext.performAndWait { 
     do { 
      try self.managedObjectContext.save() 
     } catch { 
      fatalError("Failure to save context: \(error)") 
     } 
     } 
    } catch { 
     print("Could not save \(error)") 
    } 
    } 

Il y a deux questions:

  1. Dépend sur les images, quand je cliquez sur le bouton « Terminé », l'interface utilisateur est bloqué et prend 3 - 5 secondes avant le point de vue rejeté et indiqué dans le TableView.

  2. Je vérifie la base de données réelle .sqlite et trouvé, une seule nouvelle entrée ajoutée (texte et images en UITextView) Diminue la taille de la base de données augmente presque 12MB! (Peut-être que les images prennent trop de place?)

Des suggestions pour résoudre ces problèmes? Merci!

Répondre

0

Ces problèmes seront difficiles à prévenir dans votre cas d'utilisation. En utilisant NSCoding sur un NSAttributedString qui inclut des images, ce que vous demandez est un blob binaire dans lequel vous ne pouvez pas contrôler le processus d'encodage de quelque façon que ce soit.

  • Il se peut que la taille de l'image soit gonflée, par ex. car vous enregistrez les données non compressées au lieu d'un fichier PNG ou JPEG. Mais vous ne pouvez rien faire à ce sujet, car vous ne pouvez pas contrôler la façon dont NSAttributedString le gère. Donc, vous êtes probablement bloqué avec la grande taille des données. Le temps de traitement long est probablement connecté au point précédent - vous ne pouvez pas contrôler ce que fait NSAttributedString en interne, mais il est probable qu'une grande partie de ce temps est consacré aux images.

Vous pouvez améliorer le temps de sauvegarde si vous avez codé les chaînes attribuées par vous-même au lieu d'utiliser un attribut transformable. Ensuite, vous pouvez commencer l'encodage à l'avance, en arrière-plan, au lieu de le faire lorsque vous enregistrez des données. Vous ne pouvez probablement pas corriger le temps d'encodage, mais vous pouvez le faire plus tôt et être moins visible. Je pense que vous êtes coincé avec la taille aussi longtemps que vous utilisez des chaînes codées attribuées, cependant. Je ne sais pas ce que votre application est en train de faire, mais si vous pouviez vous éloigner de NSAttributedString s énormes, vous éviterez les problèmes que vous rencontrez.

+0

Merci beaucoup pour l'explication détaillée! Tu as raison! La taille de l'image est énorme (~ 13 Mo) sans aucune compression. Et j'essayais de sauver l'image brute. origine largeur de l'image: 2448.0 origine image hauteur: 3264.0 Origine Taille de l'image en bytes: 13532006 (~ ** 13MB **!) après compression largeur de l'image: En option (750.0) après compression hauteur de l'image: Optionnel (1000.0) après compression Taille en octets: 908975 (** ~ 900kb **) Après la compression, c'est beaucoup plus rapide. Cependant, il bloque toujours l'interface utilisateur tout en sauvegardant le contexte. Comment pourrais-je l'enregistrer en arrière-plan sans bloquer mon interface utilisateur? – artekr

+0

Je pensais qu'avec un attribut de base de données binaire au lieu de transformable, vous deviez appeler vous-même les méthodes 'NSCoding'. Vous pouvez le faire avant de tenter d'enregistrer les modifications dans une file d'attente d'arrière-plan. Vous utiliseriez probablement 'NSKeyedArchiver' pour encoder et' NSKeyedUnarchiver' pour décoder. –

+0

Merci! La chose est le contenu est transformable, et je n'ai pas la possibilité de le changer en binaire. Parce que sinon je vais devoir faire une migration de base de données pour convertir tout le contenu précédent en binaire (j'ai fait une migration avant et c'était tellement pénible, et beaucoup d'utilisateurs ont même perdu leurs données :(). – artekr