创建新的NSManagedObject并将其分配给新的NSManagedObject *有时会失败

时间:2016-02-11 22:55:42

标签: swift core-data exc-bad-access

我正在创建一个名为" translation"的新NSManagedObject。在翻译中,我需要创建另外两个名为"短语"的NSManagedObjects。有时,其中一个短语赋值会抛出一个错误,但是当我检查它们时,它们看起来都很好。是什么给了???

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
    }

}

1 个答案:

答案 0 :(得分: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)
}