title: CoreData blocking UI
body: <p>I'm working on an existing project, using CoreData, that:</p>
  
  <p>Adds many many items from different CoreData Entity types, after receiving them from web service, but it blocks the UI Thread for many seconds, even if I use it in another thread.</p>
  
  <p>Please help me, is there any way to prevent CoreData from blocking UI with minimum changes as the project is almost completed?</p>
  
  <p>I'm new to <code>CoreData</code> and I don't have enough time to study the doc or reprogram the source code, unfortunately.</p>
  
  <p>My DataController:</p>
  
  <pre><code>class DataController {
  
  var managedObjectContext: NSManagedObjectContext
  let modelName = "something"
  
  
  init(closure:()-&gt;()) {
  
      guard let modelURL = NSBundle.mainBundle().URLForResource(modelName, withExtension: "momd"),
          let managedObjectModel = NSManagedObjectModel.init(contentsOfURL: modelURL)
          else {
              fatalError("DataController - COULD NOT INIT MANAGED OBJECT MODEL")
      }
  
      let coordinator = NSPersistentStoreCoordinator.init(managedObjectModel: managedObjectModel)
  
      managedObjectContext = {
          let parentContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
          parentContext.persistentStoreCoordinator = coordinator
  
          let managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
          managedObjectContext.parentContext = parentContext
          return managedObjectContext
      }()
  
      dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.rawValue), 0)) {
  
          let options = [
              NSMigratePersistentStoresAutomaticallyOption: true,
              NSInferMappingModelAutomaticallyOption: true,
              NSSQLitePragmasOption: ["journal_mode": "DELETE"]
          ]
  
          let documentsURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).last
          let storeURL = NSURL.init(string: "something", relativeToURL: documentsURL)
  
  
          do {
              try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: options)
  
              dispatch_async(dispatch_get_main_queue()) {
                  closure()
              }
          }
          catch let error as NSError {
              fatalError("DataController - COULD NOT INIT SQLITE STORE: \(error.localizedDescription)")
          }
      }
  }
  
  func save(moc: NSManagedObjectContext? = nil) {
  
      var managedObjectContext = moc
  
      if moc == nil {
          managedObjectContext = self.managedObjectContext
      }
  
      managedObjectContext!.performBlockAndWait {
  
          if managedObjectContext!.hasChanges {
  
              do {
                  try managedObjectContext!.save()
              } catch {
                  print("ERROR saving context \(managedObjectContext!.description) - \(error)")
              }
          }
  
          if let parentContext = managedObjectContext!.parentContext {
              self.save(parentContext)
          }
      }
  }
  
  
  }
  </code></pre>
  
  <p>My classes are something like:</p>
  
  <pre><code>class MOCity: NSManagedObject {
  
  @NSManaged var id: NSNumber?
  @NSManaged var name: String?
  
  // Insert code here to add functionality to your managed object subclass
  class func save(id: NSNumber, json: JSON, managedObjectContext: NSManagedObjectContext) {
  
      guard let newObject = MOCity.getById(id, create: true, managedObjectContext: managedObjectContext) else {
          fatalError("City - NO OBJECT")
      }
  
      newObject.id                &lt;-- json["Id"]
      newObject.name              &lt;-- json["Name"]
  
  }
  
  internal class func getById(id: NSNumber, create: Bool = false, managedObjectContext: NSManagedObjectContext) -&gt; MOCity? {
  
      let fetchRequest = NSFetchRequest(entityName: "City")
      fetchRequest.predicate = NSPredicate(format: "id = \(id)")
  
      do {
          guard let fetchResults = try managedObjectContext.executeFetchRequest(fetchRequest) as? [MOCity] else {
              fatalError("city - NO FETCH RESULTS")
          }
  
          if fetchResults.count &gt; 0 {
              return fetchResults.last
          }
          else if fetchResults.count == 0 {
  
              if create {
                  guard let object = NSEntityDescription.insertNewObjectForEntityForName("City", inManagedObjectContext: managedObjectContext) as? MOCity else {
                      fatalError("getCity - COULD NOT CREATE OBJECT")
                  }
                  return object
              } else {
                  return nil
              }
          }
      }
      catch let error as NSError {
      ...
      }
  
      return nil
  }
  }
  </code></pre>
  
  <p>And my web service class:</p>
  
  <pre><code>Alamofire.request(.POST, url,parameters:data).validate().responseJSON(completionHandler: {response in
  
          switch response.result {
  
          case .Success:
  
              if let jsonData = response.result.value {
  
                  if let array = jsonData as? NSArray {
  
                  for arrayItem in array {
                      MOCity.save(arrayItem["Id"] as! NSNumber, json: JSON(arrayItem as! NSDictionary)!, managedObjectContext: self.dataController.managedObjectContext)
                  }
  
                  self.dataController.save()
  
                  }
  
              }
              break
          case .Failure(let error):
          ...                
          }
  
  
      })
  </code></pre>