2016-02-11 33 views
0

我正在創建一個名爲「translation」的新NSManagedObject。在翻譯中,我需要創建另外兩個名爲「phrase」的NSManagedObject。有時候,其中一個短語任務會拋出一個錯誤,但是當我檢查這些值時,他們看起來都像是創建得很好。是什麼賦予了???創建一個新的NSManagedObject並將其分配給一個新的NSManagedObject *有時會失敗

error when adding a phrase to a translation

threads

創建翻譯對象:

func getOrCreateTranslation(package: Package?, data: NSDictionary) -> Translation { 
     let translationId = data["id"] as! NSNumber 

     if let translation = self.getTranslation(translationId) { 

      return translation 

     } else { 

      let context = LocalDataStorage().context 
      let translation = NSEntityDescription.insertNewObjectForEntityForName("Translation", inManagedObjectContext: context) as! Translation 
      translation.id = translationId 

      let fromPhrase = data["from_phrase"]! as! NSDictionary 
      let toPhrase = data["to_phrase"]! as! NSDictionary 


      let pm = PhraseManager() 

      //******* 
      // *SOMETIMES* ONE OF THESE LINES FAIL WITH BAD_EXC_ACCESS code=1 
      translation.fromPhrase = pm.getOrCreatePhrase(fromPhrase) 
      translation.toPhrase = pm.getOrCreatePhrase(toPhrase) 
      //****** 

      if package != nil { 
       package!.addTranslationObject(translation) 
      } 

      return translation 

     } 

    } 

創建一個短語對象:

func getOrCreatePhrase(data: NSDictionary) -> Phrase { 
     // check if phrase exists 
     let phraseId = data["id"] as! NSNumber 

     if let phrase = self.getPhrase(phraseId) { 

      return phrase 

     } else { 

      let context = localDataStorage.context 
      let lm = LanguageManager() 
      let phrase = NSEntityDescription.insertNewObjectForEntityForName("Phrase", inManagedObjectContext: context) as! Phrase 

      phrase.id = phraseId 
      phrase.text = data["text"] as! String 
      phrase.audioUrl = data["audio_url"] as? String 

      let code = data["language"]!["language_code"] as! String 
      phrase.language = lm.getLanguageFromCode(code) 

      return phrase 

     } 



    } 

呼叫做出API:

func getPackageTranslations(package: Package, completion: ([Translation])-> Void) { 

    let currentLanguage: Language = LanguageManager().getCurrentLanguage()! 

    let urlString = baseAPIString + "/groups/\(package.id!)/translations/?language_code=\(currentLanguage.code)" 


    let session = NSURLSession.sharedSession() 
    let serachUrl = NSURL(string: urlString) 


    let task = session.dataTaskWithURL(serachUrl!) { 
     (data, response, error) -> Void in 

     if error != nil { 
      print(error?.localizedDescription) 
     } else { 



      let jsonData: NSDictionary! 
      do { 
       jsonData = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as! NSDictionary 
      } catch _ { 
       jsonData = NSDictionary() 
      } 

      let groupTranslationsData = jsonData["group_translations"] as! [NSDictionary] 



      var translations = [Translation]() 
      let context = LocalDataStorage().context 

      for groupTranslation in groupTranslationsData { 

       let translationData = groupTranslation["translation"] as! NSDictionary 

       let translation = TranslationManager().getOrCreateTranslation(package, data: translationData) 


       if translation.packages?.containsObject(package) == false { 
        //package.addTranslationObject(translation!) 
        //translation!.addPackageObject(package) 
       } 

       translations.append(translation) 

      } 


      do { 
       try context.save() 
      } catch { 
       print("There was a problem saving translation ") 
      } 




      dispatch_async(dispatch_get_main_queue(), { 
       completion(translations) 
      }) 


     } 

    } 
    task.resume() 

} 

CoreData上下文類:

class LocalDataStorage { 
    let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate 
    let context: NSManagedObjectContext! 

    init() { 
     context = appDelegate.managedObjectContext 
    } 

} 
+0

你在哪個線程上運行以及如何配置上下文? – Wain

+1

同意。這個代碼運行在創建managedObjectContext的另一個線程上的可能性很大。當你這樣做時,它有時會起作用,有時會失敗。 – Michael

+0

謝謝你們的回覆。 @Wain,我添加了兩個更多的函數,以及上面描述的正在運行的線程的圖片。我*做*調用一個API,但對象和context.save發生在發送之前。 – Sean

回答

1

當您創建的NSManagedObjectContext與併發模式,它應該進行交互出現此問題,並執行在與初始化期間指定的併發模式不同的線程上對其執行操作。

NSURLSession.dataTaskWithURL的完成塊在另一個線程上運行,因此您必須調度到上下文創建中指定的線程類型,以便在其上成功執行任何操作。

如果上下文的併發類型是MainQueueConcurrencyType,在大多數情況下使用該類型,則必須在主隊列上執行上下文保存方法。

dispatch_async(dispatch_get_main_queue()) { 
    do { 
    try context.save() 
    } catch { 
    print("There was a problem saving translation ") 
    } 
    completion(translations) 
} 
+0

謝謝艾哈邁德!由於派遣前的其他步驟是同步的,因此我認爲他們會在派遣之前完全執行。提示後,我仍然遇到其他保存問題,並最終將整個JSON解析和對象創建移動到調度塊。現在就像一個魅力! – Sean

相關問題