2017-10-17 19 views
0

Je dois télécharger un objet CoreData sur le serveur API en arrière-plan. Pour ce faire, je crée un nouveau contexte privé en tant qu'enfant du contexte principal et je fais perform() dessus. J'utilise ce contexte pour obtenir une donnée JSON de l'objet et pour écrire des données sur l'objet après le téléchargement.Swift: synchroniser l'objet CoreData en arrière-plan

Il semble que tout fonctionne bien mais j'ai quelques doutes.

Voici un exemple simple qui montre le cas. Le contexte a-t-il une forte référence dans la seconde fonction? Devrais-je garder une référence forte à mon nouveau contexte quelque part?

// ViewController.swift 
func uploadObject(_ currentObject: MyManagedObject) { 
    // we are in the main thread, go to another thread 
    let objectId = currentObject.objectID 
    let context = getNewPrivateContext() // child context of the main context 
    context.perform { 
     if let object = context.object(with: objectId) as? MyManagedObject { 
      SyncManager.shared.uploadObject(_ object: object, completion: { 
       // ... update UI 
      }) 
     } 
    } 
} 

// SyncManager.swift 
func uploadObject(_ object: MyManagedObject, completion:()->()) { 
    // does the context has some strong reference here? 
    guard let context = object.managedObjectContext { completion(); return } 

    let params = getJson(with: object) 
    // ... prepare url, headers 
    Alamofire.request(url, method: .put, parameters: params, encoding: JSONEncoding.default, headers: headers) 
     .responseJSON(completionHandler: { (response) in 
      // ... parse the response 
      context.perform { 
       // ... write some data to the Core Data and save the context 
       completion() 
      } 
     }) 
} 

EDIT

aussi mes doutes sont pris en charge par un problème de LLDB:

(lldb) po context 
error: <EXPR>:3:1: error: use of unresolved identifier 'context' 
context 
^~~~~~~ 
+0

Tout me semble bon – Ladislav

+0

Sachez que 'context.object (avec: objectId)' va générer un nouvel objet pour toi. Vous voulez probablement 'existingObject (avec:)' – jrturton

Répondre

0

Il est une référence forte, mais il est dangereux, ce qui signifie que si le récepteur (l'objet) est supprimé De son contexte, il reviendra à zéro.

Juste mon avis, je voudrais utiliser une déclaration if let à la place d'un gardien:

func uploadObject(_ object: MyManagedObject, completion:()->()) { 
    // does the context has some strong reference here? 
    if let context = object.managedObjectContext { 

     let params = getJson(with: object) 
     // ... prepare url, headers 
     Alamofire.request(url, method: .put, parameters: params, encoding: JSONEncoding.default, headers: headers) 
    .responseJSON(completionHandler: { (response) in 
      // ... parse the response 
      context.perform { 
       // ... write some data to the Core Data and save the context 
       completion() 
      } 
     }) 
    } else { 
     completion() 
    } 
} 
+0

object.managedObjectContext() est juste une faute de frappe. Fixé. –

+0

Changer 'guard' à' if let' n'a pas de sens. Cela ajoute simplement l'imbrication inutile du code. –

+0

Désolé pour ça :), eh bien c'est le seul problème que j'ai vu ... vous sauvegardez le privateMOC, qui va pousser ses changements à son MOC parent ... Je ne voulais pas dire que c'était mieux, juste deux façons différentes gérer les options. Dans les deux cas, ce bloc de code n'est exécuté que si 'context' est défini –