2015-02-25 3 views
0

В настоящее время я разрабатываю игру, в которой сферы падают с неба. Собирая сферы, вы получаете очки, и после определенного количества очков все сферы ускоряются до другой скорости.Swift - многопоточная многопоточная обработка GCD, «мутированная при перечислении»

  1. Новые сферы непрерывно добавляют в массив (4 Spheres внутри каждого SKNode).
  2. Когда они ускоряются, я повторяю массив, чтобы увеличить скорость всех из них.
  3. Когда сферы выпадают из экрана, я удаляю их из массива.
class GameScene: SKScene, SKPhysicsContactDelegate { 
... 
var allActiveNodes = Array<SKNode>() 
private let concurrentNodesQueue = dispatch_queue_create(
    "com.SphereHunt.allActiveNodesQueue", DISPATCH_QUEUE_CONCURRENT) 
... 

//1. This is where the new spheres are added to the Array via a new thread 
func addSpheres(leftSphere: Sphere, middleLeftSphere: Sphere, middleRightSphere: Sphere, rightSphere: Sphere){ 
... 
dispatch_barrier_async(self.concurrentNodesQueue){ 
     self.allActiveNodes.append(containerNode) 
     let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 
     dispatch_async(queue) { 
//Set the new spheres in motion 
      self.runPastAvatar(containerNode) 
     } 
    } 

//2. This function starts a thread that will increase the speed of all active spheres 
    func increaseSpeed20percent(){ 
     durationPercentage = durationPercentage * 0.8 
     dispatch_sync(self.concurrentNodesQueue){ 
     let copyAllActiveNodes = self.allActiveNodes 
     let count = copyAllActiveNodes.count 

     for index in 0...count-1{ 
      let node = copyAllActiveNodes[index] 
      node.removeAllActions() 
      self.runPastAvatar(node) 
     } 
    } 
} 
//3. This method removes the sphere that is not in screen anymore from the Array 
    func removeLastNode(node: SKNode){ 
    dispatch_barrier_async(self.concurrentNodesQueue){ 
      self.allActiveNodes.removeAtIndex(0) 
      node.removeFromParent() 
      println("Removed") 
      } 
    } 

Я не уверен, если я понял НОД правильно, я попробовал несколько решений, и это один я был уверен, что будет работать. Я всегда получаю такое же сообщение об ошибке:

*** Terminating app due to uncaught exception 'NSGenericException', 
reason: '*** Collection <__NSArrayM: 0x17004c9f0> was mutated while being enumerated.' 

Как заставить потоки не мешать друг другу при работе с массивом?

ответ

0

Моя проблема заключалась в том, что я использовал решение «нить-сон» для запуска новых сфер за промежуток времени. Это был плохой выбор, но, на мой взгляд, не должно было появляться такое сообщение об ошибке. Я решил использовать NSTimer для запуска новых сфер за промежуток времени. Это дало игре немного отставание, но оно более надежное и не потерпит краха. Далее мы узнаем, как использовать NSTimer, не создавая такого отставания в игре!

0

Я не уверен, если это вопрос, но из документов для:

func dispatch_sync(_ queue: dispatch_queue_t, 
      _ block: dispatch_block_t) 

В отличие от dispatch_async, не сохраняют выполняется на целевой очереди. Поскольку вызовы этой функции синхронны, она «заимствует» ссылку вызывающего абонента. Более того, на блоке блока Block_copy не выполняется.

> В качестве оптимизации эта функция вызывает, когда это возможно, блок на текущем потоке .

Я выделил важную часть здесь. Почему бы вам не назвать цикл с помощью dispatch_barrier_sync.

+0

Я пробовал вызывать цикл с dispatch_barrier_sync, но проблема остается. – hardyfelix

+0

Я прокомментировал все, что имело отношение к массиву, и у меня все еще такое же сообщение об ошибке. Это очень странно, потому что никакой другой массив не манипулируется подобным образом. Как я могу отладить это? Сообщение об ошибке «Collection <__ NSArrayM: 0x17004c9f0> ...» показывает идентификатор массиву, но при просмотре кода массивы не получают никаких идентификаторов. Как я могу найти конкретный массив, который находится за ручкой, тем самым давая это сообщение об ошибке? – hardyfelix

+0

Я прокомментировал буквально все. Теперь я начинаю только 1 поток, который добавляет больше сфер, а затем спит в течение продолжительности. Я всегда получаю то же сообщение об ошибке, когда поток спит, ничего не работает, а спящий поток. Может ли быть проблема с функцией сна внутри потока? Но ничего подобного не должно приводить к тому, что «<__ NSArrayM: 0x170048e20> мутировался при перечислении». – hardyfelix

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