2015-07-24 1 views
0

Je charge des informations du site dans json vers des données de base locales. J'ai créé 2 sous-classes de NSManagedObject:Meilleure façon de charger des informations à partir de la base de données du serveur

@objc(Category) 
class Category: NSManagedObject { 
    @NSManaged var id: NSNumber 
    @NSManaged var name: String 
} 

@objc(Event) 
class Event: NSManagedObject { 
    @NSManaged var category: String 
    @NSManaged var date: String 
    @NSManaged var event: String 
    @NSManaged var location: String 
    @NSManaged var time: String 
} 

Et voici le code où je charger des informations en arrière-plan:

func loadAllData(){ 
    println("loading all data") 

    progressCounter = 0 

    let source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue()); 

    dispatch_source_set_event_handler(source) { 
     [unowned self] in 
     self.progressCounter += dispatch_source_get_data(source) 
     self.progressView.setProgress(Float(self.progressCounter)/Float(self.maxValue), animated: true) 
    } 

    dispatch_resume(source) 

    let params = ServerConstants.infoParam + "=true" 

    // creating request, set its method to POST and append params to request 
    var request = NSMutableURLRequest(URL: NSURL(string: ServerConstants.getInfoURL)!) 
    request.HTTPMethod = "POST" 
    request.HTTPBody = params.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) 
    //request.setValue("Basic \(base64LoginString!)", forHTTPHeaderField: "Authorization") 

    //start loading data in background 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) { 
     var session = NSURLSession.sharedSession() 
     var task = session.dataTaskWithRequest(request){ (data, response, error) -> Void in 
      if error == nil { 
       let json = JSON(data: data) 

       //println(json) 
       self.maxValue = Float(json["categories"].count + json["events"].count) 
       println("maxself. - \(self.maxValue)") 

       var array = json["categories"] 
       var maxIndex = array.count 

       var error: NSError? 
       for var i: Int = 0; i < maxIndex; i++ { 
        if let moc = self.context { 
         let newItem = NSEntityDescription.insertNewObjectForEntityForName("Category", inManagedObjectContext: self.context!) as! Category 

         newItem.id = array[i]["id"].string!.toInt()! 
         newItem.name = array[i]["name"].string! 

         dispatch_source_merge_data(source, 1); 
         moc.save(&error) 
        } 
       } 

       array = json["events"] 
       maxIndex = array.count 

       for var i: Int = 0; i < maxIndex; i++ { 
        if let moc = self.context { 
         let newItem = NSEntityDescription.insertNewObjectForEntityForName("Event", inManagedObjectContext: moc) as! Event 

         newItem.category = array[i]["category"].string! 
         newItem.event = array[i]["event"].string! 
         newItem.location = array[i]["location"].string! 
         newItem.date = array[i]["date"].string! 
         newItem.time = array[i]["time"].string! 

         dispatch_source_merge_data(source, 1); 
         moc.save(&error) 
        } 
       }     
       println("done") 
       dispatch_async(dispatch_get_main_queue()){ 
        self.showScreenElements() 
       } 
      } 
     } 
     task.resume() 
    } 
} 

Ma base de données de serveur a environ 3600 lignes et le processus de téléchargement prend ~ 30- 40 secondes pour charger.

Existe-t-il un meilleur moyen de récupérer le serveur JSON plus rapidement?

Quand j'ai essayé de sauver une seule fois à 200 itérations il lancer est une erreur

EXC_BAD_ACCESS

for var i: Int = 0; i < maxIndex; i++ { 
    if let moc = self.context { 
     let newItem = NSEntityDescription.insertNewObjectForEntityForName("Event", inManagedObjectContext: moc) as! Event 
     newItem.category = array[i]["category"].string! 
     ... 
     dispatch_source_merge_data(source, 1); 
     if i % 200 == 0 { 
      moc.save(&error) 
     } 
    } 
} 
self.context!.save(&error) 
println("done") 

Je vais essayer d'utiliser performBlock et vous dire mes résultats.

Répondre

0

Vous économisez trop souvent. Essayez d'enregistrer par lots, disons après environ 500 insertions.

Également, essayez de basculer du gestionnaire d'annulation du contexte pour cette opération. En supposant que vous avez un contexte enfant que vous pouvez défausser:

context.undoManager = nil 

En outre, votre code GCD est assez compliqué. Avez-vous regardé les API performBlock et performBlockAndWait de NSManagedObjectContext?

+0

s'il vous plaît, vérifiez ma réponse mise à jour – mikle94