应用程序不断崩溃,由于未捕获的异常而终止应用程序 'NSInvalidArgumentException'

app keeps crashing , Terminating app due to uncaught exception 'NSInvalidArgumentException'

我正在创建一个游戏,其中随机物体落在随机位置并且有一个具有固定 y 轴并沿 x 轴移动的球,它必须移动并抛出物体,我正在尝试计算分数的方法是我创建了一个物理对象,它与球位于同一 y 轴上,当对象发生碰撞时,应该调用分数函数并将分数增加 1,但是对于由于某种原因,该应用程序不断崩溃,它给了我这个错误。

2015-07-13 01:23:17.242 WalkRun[26792:3773366] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attemped to add a SKNode which already has a parent: <SKSpriteNode> name:'(null)' texture:[<SKTexture> 'shortwall' (60 x 60)] position:{30, 768} size:{60, 60} rotation:0.00'
*** First throw call stack:
(
    0   CoreFoundation                      0x00000001073c33f5 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x00000001092eabb7 objc_exception_throw + 45
    2   CoreFoundation                      0x00000001073c332d +[NSException raise:format:] + 205
    3   SpriteKit                           0x0000000107ebfaf6 -[SKNode addChild:] + 111
    4   WalkRun                             0x00000001071c8c44 _TFC7WalkRun9PlayScene10leftObjectfS0_FT_T_ + 2868
    5   WalkRun                             0x00000001071c7ddc _TFC7WalkRun9PlayScene10randObjectfS0_FT_T_ + 236
    6   WalkRun                             0x00000001071c8102 _TToFC7WalkRun9PlayScene10randObjectfS0_FT_T_ + 34
    7   Foundation                          0x0000000107a39fd4 __NSFireTimer + 83
    8   CoreFoundation                      0x000000010732b4e4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
    9   CoreFoundation                      0x000000010732b0a5 __CFRunLoopDoTimer + 1045
    10  CoreFoundation                      0x00000001072ee3dd __CFRunLoopRun + 1901
    11  CoreFoundation                      0x00000001072eda06 CFRunLoopRunSpecific + 470
    12  GraphicsServices                    0x000000010e7569f0 GSEventRunModal + 161
    13  UIKit                               0x0000000108046550 UIApplicationMain + 1282
    14  WalkRun                             0x00000001071d54ce top_level_code + 78
    15  WalkRun                             0x00000001071d550a main + 42
    16  libdyld.dylib                       0x0000000109ad9145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

这是我的代码:

//
//  PlayScene.swift
//  WalkRun
//
//  Created by naeim on 7/10/15.
//  Copyright (c) 2015 naeim. All rights reserved.
//

import Foundation
import SpriteKit

class PlayScene: SKScene, SKPhysicsContactDelegate{

    var ball = SKSpriteNode(imageNamed: "ball")
    var wall = SKNode()
    var wallRight = SKNode()
    var wallMiddle = SKNode()
    var ballSpeed = CGFloat()

    var bigWall = SKSpriteNode(imageNamed: "shortwall")
    var tallWall = SKSpriteNode(imageNamed: "tallwall")

    var ballGroup:UInt32 = 1
    var objectGroup:UInt32 = 2
    var gapGroup:UInt32 = 3

    var gameOver = 0

    var movingObjects = SKNode()

    var score = 0
    var scoreLabel = SKLabelNode()

    override func didMoveToView(view: SKView) {

        self.physicsWorld.contactDelegate = self

        backgroundColor = UIColor(hex: 0x80d9ff)
        self.physicsWorld.gravity = CGVectorMake(-9,0)

        self.addChild(movingObjects)

        //creating the ball
        ball.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMinY(self.frame) + self.ball.size.height * 2)
        ball.physicsBody = SKPhysicsBody(circleOfRadius: self.ball.size.width / 2)
        ball.zPosition = 10


        //let the ball rotate forever
        ballSpeed = 3
        let rotateAction = SKAction.rotateByAngle(ballSpeed, duration: 1)
        let repeatAction = SKAction.repeatActionForever(rotateAction)
        ball.runAction(repeatAction)
        ball.physicsBody?.categoryBitMask = ballGroup
        ball.physicsBody?.collisionBitMask = objectGroup
        ball.physicsBody?.contactTestBitMask = objectGroup

        self.addChild(ball)

        //creating the wall of the left
        wall.position = CGPointMake(CGRectGetMinX(self.frame),CGRectGetMinY(self.frame))
        wall.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(2, self.frame.size.height * 2.0))
        wall.physicsBody?.dynamic = false
        wall.physicsBody?.categoryBitMask = objectGroup
        self.addChild(wall)

        //creating the wall of the right
        wallRight.position = CGPointMake(CGRectGetMaxX(self.frame), CGRectGetMinY(self.frame))
        wallRight.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(2, self.frame.size.height * 2.0))
        wallRight.physicsBody?.dynamic = false
        wallRight.physicsBody?.categoryBitMask = objectGroup
        self.addChild(wallRight)

        //creating the middle wall that objects pass by
        wallMiddle.position = CGPointMake(CGRectGetMinX(self.frame), CGRectGetMinY(self.frame))
        wallMiddle.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(self.frame.size.width, 1))
        wallMiddle.physicsBody?.dynamic = false
        wallMiddle.physicsBody?.categoryBitMask = gapGroup
        wallMiddle.physicsBody?.collisionBitMask = gapGroup
        wallMiddle.physicsBody?.contactTestBitMask = objectGroup
        self.addChild(wallMiddle)

        //creating the label
        scoreLabel.fontName = "Helvetica"
        scoreLabel.fontSize = 60
        scoreLabel.text = "0"
        scoreLabel.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) + 70 )
        self.addChild(scoreLabel)

        var timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("randObject"), userInfo: nil, repeats: true)

        var timerObjects = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: Selector("checkObjectPlace"), userInfo: nil, repeats: true)


    }

    func checkObjectPlace(){



    }

    //function to randomly choose which object

    func randObject(){
        if gameOver == 0{

        var rand = arc4random_uniform(6)+1

        switch(rand){

        case 1:
            leftObject()
        case 2:
            middleObject()
        case 3:
            rightObject()
        case 4:
            LeftAndMiddleObject()
        case 5:
            rightAndLeftObject()
        case 6:
            rightAndMiddleObject()
        default:
            println("error !! non a number other than 0, 1, 2 has been choosen .")

            }

        }
    }

    //function to create the left objects

    func leftObject(){
        var rand = arc4random_uniform(2) + 1
        if rand == 1
        {

             bigWall.position = CGPointMake(CGRectGetMinX(self.frame) + bigWall.size.width / 2, CGRectGetMaxY(self.frame))

            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
            bigWall.runAction(moveAndRemoveObjects)
            bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
            bigWall.physicsBody?.dynamic = false
            bigWall.physicsBody?.categoryBitMask = objectGroup

            movingObjects.addChild(bigWall)

        }
        else
        {

            tallWall.position = CGPointMake(CGRectGetMinX(self.frame) + tallWall.size.width / 2, CGRectGetMaxY(self.frame))
            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
            tallWall.runAction(moveAndRemoveObjects)
            tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
            tallWall.physicsBody?.dynamic = false

            tallWall.physicsBody?.categoryBitMask = objectGroup


            movingObjects.addChild(tallWall)
        }


    }

    //function to create the middle objects

    func middleObject(){

        var rand = arc4random_uniform(2) + 1
        if rand == 1
        {
            var bigWall = SKSpriteNode(imageNamed: "shortwall")
            bigWall.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame))
            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
            bigWall.runAction(moveAndRemoveObjects)
            bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
            bigWall.physicsBody?.dynamic = false
            bigWall.physicsBody?.categoryBitMask = objectGroup
            movingObjects.addChild(bigWall)
        }
        else
        {
            var tallWall = SKSpriteNode(imageNamed: "tallwall")
            tallWall.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame))
            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
            tallWall.runAction(moveAndRemoveObjects)
            tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
            tallWall.physicsBody?.dynamic = false
            tallWall.physicsBody?.categoryBitMask = objectGroup
            movingObjects.addChild(tallWall)
        }

    }

    //function to create the right objects

    func rightObject(){
        var rand = arc4random_uniform(2) + 1
        if rand == 1
        {
            var bigWall = SKSpriteNode(imageNamed: "shortwall")
            bigWall.position = CGPointMake(CGRectGetMaxX(self.frame) - bigWall.size.width / 2, CGRectGetMaxY(self.frame))
            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
            bigWall.runAction(moveAndRemoveObjects)
            bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
            bigWall.physicsBody?.dynamic = false
            bigWall.physicsBody?.categoryBitMask = objectGroup
            movingObjects.addChild(bigWall)

        }
        else
        {
            var tallWall = SKSpriteNode(imageNamed: "tallwall")
            tallWall.position = CGPointMake(CGRectGetMaxX(self.frame) - tallWall.size.width / 2, CGRectGetMaxY(self.frame))
            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
            tallWall.runAction(moveAndRemoveObjects)
            tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
            tallWall.physicsBody?.dynamic = false
            tallWall.physicsBody?.categoryBitMask = objectGroup
            movingObjects.addChild(tallWall)

            if ball.position.x == tallWall.position.x{
                scoreIncrement()
            }
        }


    }

    //function to create a right and left object

    func rightAndLeftObject(){

        var rand = arc4random_uniform(2) + 1
        if rand == 1
        {
            var bigWall = SKSpriteNode(imageNamed: "shortwall")
            var tallWall = SKSpriteNode(imageNamed: "tallwall")
            tallWall.position = CGPointMake(CGRectGetMinX(self.frame) + tallWall.size.width / 2, CGRectGetMaxY(self.frame))
            bigWall.position = CGPointMake(CGRectGetMaxX(self.frame) - bigWall.size.width / 2, CGRectGetMaxY(self.frame))
            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
            bigWall.runAction(moveAndRemoveObjects)
            tallWall.runAction(moveAndRemoveObjects)
            tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
            tallWall.physicsBody?.dynamic = false
            bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
            bigWall.physicsBody?.dynamic = false
            bigWall.physicsBody?.categoryBitMask = objectGroup
            tallWall.physicsBody?.categoryBitMask = objectGroup
             movingObjects.addChild(tallWall)
            movingObjects.addChild(bigWall)

                        bigWall.position = CGPointMake(CGRectGetMaxX(self.frame) - bigWall.size.width / 2, CGRectGetMaxY(self.frame))
        }
        else
        {
            var bigWall = SKSpriteNode(imageNamed: "shortwall")
            var tallWall = SKSpriteNode(imageNamed: "tallwall")
            bigWall.position = CGPointMake(CGRectGetMaxX(self.frame) - bigWall.size.width / 2, CGRectGetMaxY(self.frame))
            tallWall.position = CGPointMake(CGRectGetMaxX(self.frame) - tallWall.size.width / 2, CGRectGetMaxY(self.frame))
            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
            tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
            tallWall.physicsBody?.dynamic = false
            bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
            bigWall.physicsBody?.dynamic = false
            tallWall.runAction(moveAndRemoveObjects)
            bigWall.runAction(moveAndRemoveObjects)
            bigWall.physicsBody?.categoryBitMask = objectGroup
            tallWall.physicsBody?.categoryBitMask = objectGroup
            movingObjects.addChild(tallWall)
            movingObjects.addChild(bigWall)
        }


    }

    func rightAndMiddleObject(){

        var rand = arc4random_uniform(2) + 1
        if rand == 1
        {
            var bigWall = SKSpriteNode(imageNamed: "shortwall")
            var tallWall = SKSpriteNode(imageNamed: "tallwall")
            tallWall.position = CGPointMake(CGRectGetMaxX(self.frame) - tallWall.size.width / 2, CGRectGetMaxY(self.frame))
            bigWall.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame))

            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])

            tallWall.runAction(moveAndRemoveObjects)
            bigWall.runAction(moveAndRemoveObjects)
            tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
            tallWall.physicsBody?.dynamic = false
            bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
            bigWall.physicsBody?.dynamic = false
            bigWall.physicsBody?.categoryBitMask = objectGroup
            tallWall.physicsBody?.categoryBitMask = objectGroup
            movingObjects.addChild(tallWall)
            movingObjects.addChild(bigWall)

        }
        else
        {
            var bigWall = SKSpriteNode(imageNamed: "shortwall")
            var tallWall = SKSpriteNode(imageNamed: "tallwall")
            bigWall.position = CGPointMake(CGRectGetMidX(self.frame) , CGRectGetMaxY(self.frame))
            tallWall.position = CGPointMake(CGRectGetMaxX(self.frame) - tallWall.size.width / 2, CGRectGetMaxY(self.frame))
            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])

            tallWall.runAction(moveAndRemoveObjects)
            bigWall.runAction(moveAndRemoveObjects)
            tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
            tallWall.physicsBody?.dynamic = false
            bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
            bigWall.physicsBody?.dynamic = false
            bigWall.physicsBody?.categoryBitMask = objectGroup
            tallWall.physicsBody?.categoryBitMask = objectGroup
            movingObjects.addChild(tallWall)
            movingObjects.addChild(bigWall)
        }


    }

    func LeftAndMiddleObject(){

        var rand = arc4random_uniform(2) + 1
        if rand == 1
        {
            var bigWall = SKSpriteNode(imageNamed: "shortwall")
            var tallWall = SKSpriteNode(imageNamed: "tallwall")
            tallWall.position = CGPointMake(CGRectGetMinX(self.frame) + tallWall.size.width / 2, CGRectGetMaxY(self.frame))
            bigWall.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame))

            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])

            tallWall.runAction(moveAndRemoveObjects)
            bigWall.runAction(moveAndRemoveObjects)
            tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
            tallWall.physicsBody?.dynamic = false
            bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
            bigWall.physicsBody?.dynamic = false
            bigWall.physicsBody?.categoryBitMask = objectGroup
            tallWall.physicsBody?.categoryBitMask = objectGroup
            movingObjects.addChild(tallWall)
            movingObjects.addChild(bigWall)

        }
        else
        {
            var bigWall = SKSpriteNode(imageNamed: "shortwall")
            var tallWall = SKSpriteNode(imageNamed: "tallwall")
            bigWall.position = CGPointMake(CGRectGetMidX(self.frame) , CGRectGetMaxY(self.frame))
            tallWall.position = CGPointMake(CGRectGetMinX(self.frame) + tallWall.size.width / 2, CGRectGetMaxY(self.frame))

            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])

            tallWall.runAction(moveAndRemoveObjects)
            bigWall.runAction(moveAndRemoveObjects)
            tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
            tallWall.physicsBody?.dynamic = false
            bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
            bigWall.physicsBody?.dynamic = false
            bigWall.physicsBody?.categoryBitMask = objectGroup
            tallWall.physicsBody?.categoryBitMask = objectGroup
            movingObjects.addChild(tallWall)
            movingObjects.addChild(bigWall)
        }


    }

    func scoreIncrement(){

        score = score + 1
       scoreLabel.text = "\(score)"
    }


    func didBeginContact(contact: SKPhysicsContact) {

        println("contact")

        if  contact.bodyA.categoryBitMask == gapGroup || contact.bodyB.categoryBitMask == gapGroup {

            println("gap contact")

        } else {

            gameOver = 1
            movingObjects.speed = 0

        }
    }

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        if gameOver == 0 {

        ball.physicsBody?.velocity = CGVectorMake(0, 0)
        ball.physicsBody?.applyImpulse(CGVectorMake(70,0))

        }

    }

    override func update(currentTime: NSTimeInterval) {



    }
}

该错误表明您正在尝试向已有父节点的节点添加子节点。堆栈跟踪将您指向 leftObject 方法。在这里,您有一个 SKAction 设置,可以在一段时间内移动,然后从父对象中删除。

        var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
        var removeObjects = SKAction.removeFromParent()
        var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
        bigWall.runAction(moveAndRemoveObjects)

这会将操作添加到节点并运行,但您的代码路径将继续向下到

    movingObjects.addChild(bigWall)

几乎是瞬间。看起来像一个竞争条件,您认为代码将等到操作完成 运行 后再继续。

您有一个名为 bigWall 的实例 属性,在您的大多数方法中,您创建了一个名为 bigWall 的本地对象并将其添加到场景中。因为每次调用方法时它都是一个新对象,所以工作正常。但是,在方法 leftObject 中,您没有本地对象 bigWall,因此它引用了实例 属性。第一次调用 leftObject 时,将实例 属性 bigWall 添加到场景中会很好。第二次调用该方法时,它会尝试将 bigWall 实例 属性 添加到场景中,此时它已经在场景中,这就是您会收到错误的地方。