2016-04-24 3 views
0

Я пытаюсь загрузить фотографии в Core Data, но для этого требуются некоторые фоновые потоки, поэтому бывает, что мой объект будет сохранен в Core Data без его фотографии, я получаю, что фотография равна нулю. И то же самое происходит с фотографиями моих групп.Выполнение всех фоновых потоков перед выполнением другого блока

Короче говоря, на каждой итерации я сохраняю объект в Core Data, и сохранение происходит быстрее, чем загрузка моих данных Фото.

Я пробовал Семафоры, барьеры, группы, ... но никто не работал. Я, конечно, делаю что-то неправильно, но я не знаю, что. Если бы кто-то мог мне помочь, я бы очень признателен, это было 2 недели, когда я борюсь с этой же проблемой. Это мой код в упрощенной версии, полная версия доступна ниже:

// MARK - ViewDidLoad 
override func viewDidLoad() { 
    // This method is only called once, so you want to create any controls or arrays here 
    super.viewDidLoad() 

    // Verifying connectivity to internet 
    if Reachability.isConnectedToNetwork() == true { 

    // Getting data from Parse + getDataInBackgroundWithBlock 

    }else{ 

    } 
} 


// MARK - Action of the login button 
@IBAction func loginBtn_click(sender: AnyObject) { 
    if usernameTxt.text == "" || passwordTxt.text == "" { 
     self.displayAlert("Error", message: "Please enter a username and password") 
    }else{ 

     // MARK - Login the user 
     PFUser.logInWithUsernameInBackground(usernameTxt.text!, password: passwordTxt.text!) { (user, error) -> Void in 

      if error == nil { 

       let queue = dispatch_queue_create("com.karagan.app.queue", DISPATCH_QUEUE_CONCURRENT) 

       dispatch_async(queue, {() -> Void in 
        self.getObjectsFromQueryWithAscendingOrder("Add", key: "user", value: userName, ascendingOrder: "added", completionHandler: { (objects1) -> Void in 

       // Update of an array in background 

        }) 
       }) 



       dispatch_async(queue, {() -> Void in 

       // Update of an array in background 

       }) 



       dispatch_async(queue, {() -> Void in 
        self.getObjectsFromQueryWithAscendingOrder("Group", key: "membersUsername", value: userName, ascendingOrder: "membersUsername", completionHandler: { (objects3) -> Void in 

       // Update of an array in background 

         // MARK - Adding all the users in Core data 
         for var i = 0; i < usersFromParseDataBase.count; i++ { 

          let entity = NSEntityDescription.entityForName("Users", inManagedObjectContext: self.managedObjectContext) 
          let newUser = Users(entity: entity!, insertIntoManagedObjectContext: self.managedObjectContext) 
          if self.arrayAddedUsers.contains(usersFromParseDataBase[i].username){ 

       // Saving new records in Core Data     

          } 
         } 
        }) 
       }) 

       dispatch_async(queue, {() -> Void in 
        self.getObjectsFromQueryWithDescendingOrder("Group", key: "membersUsername", value: userName, descendingOrder: "conversationUpdate", completionHandler: { (objects4) -> Void in 

          if array.count == 2 { 

        // Getting data in background - photo.getDataInbackgroundWithBlock     

           } 
          }else{ 

       // Getting data in background - photo.getDataInbackgroundWithBlock 

          } 
         } 
        }) 
       }) 

       dispatch_barrier_async(queue, {() -> Void in 

     // Doing some stuff in background which needs the data from threads above 

       }) 

      }else{ 
       // Print error from loginWithUsernaemInBackground 
      } 
     } 
    } 
} 

Это то, что получает отображается в журнал, так что вы можете ясно видеть, что барьер запускается на выполнение до загрузки изображений осуществляется выполнение ,

TEST 3 - interacting user has been saved to core data 
Loading profile image 
Loading profile image 
Loading group image 
Loading profile image 
Loading profile image 
9 
5 
Loading group image 
Loading group image 
Loading group image 
Loading group image 

Дело в том, что мне нужны эти данные для других операций позже. Мой код несовместим.

+1

Вы можете захотеть взглянуть на dispatch_group_create(), dispatch_group_wait() и dispatch_group_async(), чтобы иметь группу задач, которые вы хотите дождаться, прежде чем продолжить. Эта ссылка может помочь: http://stackoverflow.com/questions/11909629/waiting-until-two-async-blocks-are-executed-before-starting-another-block –

+0

Если блоки кода, которые вы отправляете, сами, асинхронные задачи, вам может потребоваться явно «dispatch_group_enter' /' leave ». Будет сложно диагностировать вашу проблему или сообщить далее, не видя код, который генерирует эти сообщения журнала. Или, честно говоря, потому что ваш код настолько сложный, вы можете захотеть построить [гораздо более простой, воспроизводимый пример] (http://stackoverflow.com/help/mcve), который проявляет описанную вами ошибку. – Rob

+0

Привет, Роб, я добавил более простую версию моего кода только с наиболее важными частями. Является ли это всеобъемлющим? Если нет, я могу попытаться сделать это проще. Спасибо за вашу помощь. dee zg, я уже пробовал dispatch_group_create() ... но у меня все еще была та же проблема. Просто я не знаю, как правильно его реализовать. Я всегда получаю ту же проблему, если не добавить «sleep (Uint32)» к моему последнему блоку, но это непротиворечиво. – C00kieMonsta

ответ

-1

Я думаю, что вы на правильном пути. Когда я создаю простую программу и использовать dispatch_barrier_async он отлично работает:

let queue = dispatch_queue_create("com.karagan.app.queue", DISPATCH_QUEUE_CONCURRENT) 

dispatch_async(queue, {() -> Void in 
    sleep(1) 
    print("1") 
}) 

dispatch_async(queue, {() -> Void in 
    sleep(2) 
    print("2") 
}) 

dispatch_async(queue, {() -> Void in 
    sleep(3) 
    print("3") 
}) 

dispatch_async(queue, {() -> Void in 
    sleep(4) 
    print("4") 
}) 

dispatch_barrier_async(queue, {() -> Void in 
    print("done") 
}) 

Выход:

1 
2 
3 
4 
done 

Я думаю, что проблема в том, что dispatch_async не ждет вызова PFFile.getDataInBackgroundWithBlock закончить:

photoFile.getDataInBackgroundWithBlock({ (imageData, error) -> Void in 
    if error == nil { 
     self.arrayImageFiles.append(imageData!) 
     print("Loading group image") 
    } 
}) 

Попробуйте переключить все вызовы на getDataInBackgroundWithBlock с синхронным вызовом на PFFile.getData (444459450) 37313489927653748888 :) вместо:

var imageData = photoFile.getData 
if (imageData != nil) { 
    self.arrayImageFiles.append(imageData!) 
} 

Это не должно действительно иметь никаких проблем с производительностью, так как вы уже выполнения этого кода асинхронно.

+0

Спасибо Оценка за ваш ответ. Мне еще нужно сделать несколько тестов, но это может мне помочь.Я не знал, что можно загрузить данные изображения в основной поток. Я очень ценю вашу помощь и буду информировать вас, действительно ли это решает мою проблему. – C00kieMonsta

+0

Использование 'dispatch_barrier_async' _can only_ может использоваться как« дозорный », если ранее отправленные задачи в одну очередь были _synchronous_. Однако в случае OPs они асинхронны. То есть, вызов возвращает _immediately_ и - для очереди - этот блок завершен. – CouchDeveloper

+0

@CouchDeveloper Это то, что я сказал в своем ответе и почему я рекомендовал сделать эти задачи синхронными. Я что-то упускаю? – markwatsonatx

Смежные вопросы