0

我目前正在开发一个球体从天而降的游戏。在收集球体时,您会获得积分,并且在获得一定数量的积分后,所有球体都会加速到另一个速度。

  1. 新球体不断添加到一个阵列中(每个 SKNode 内有 4 个球体)。
  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")
            }
    }

我不确定我是否正确理解了 GCD,我尝试了多种解决方案,这是我确信会起作用的解决方案。我总是得到同样的错误信息:

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

如何让线程在处理数组时不会相互干扰?

4

2 回答 2

0

我不确定这是否是问题,但来自以下文件:

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

与 dispatch_async 不同,目标队列不执行保留。因为对该函数的调用是同步的,所以它“借用”了调用者的引用。此外,不会对块执行 Block_copy。

> 作为优化,此函数在可能的情况下调用当前线程上的块。

我在这里加粗了重要的部分。为什么不用 adispatch_barrier_sync来调用循环。

于 2015-02-25T21:03:39.437 回答
0

我的问题是我使用线程睡眠解决方案在时间间隔内发射新球体。这是一个糟糕的选择,但在我看来不应该产生这样的错误消息。我使用 NSTimer 在时间间隔内发射新球体来解决它。这给游戏带来了一些延迟,但它更强大并且不会崩溃。接下来是找出如何使用 NSTimer 而不会在游戏中造成这样的延迟!

于 2015-02-26T22:42:30.010 回答