Search code examples
iphonecrashsprite-kitskphysicscontact

App crashes on iPhone 4s but no other device: possible issue with SKPhysicsContactDelegate?


I've ran my spritekit game on the following devices: iPhone 5s, iPhone 4s, iPad air and iPad mini. The app runs and all the devices except the 4s. On the 4s the app crashes when the app transitions to scenes that include SKPhysicsContactDelegate, for example:

class PlayScene: SKScene, SKPhysicsContactDelegate, ADBannerViewDelegate {


 enum ColliderType: UInt32 {

    case  narrowCategory = 1
    case  bigCategory = 2
    case  smallCategory = 4
    case  roundCategory = 8

}

var narrow = SKSpriteNode(imageNamed: "Narrow")
var big = SKSpriteNode(imageNamed: "Big")

override func didMoveToView(view: SKView) {
   ........ }

The error message that comes up when the app crashes is: thread 1 exc_breakpoint (code=exc_arm_breakpoint, subcode = 0xe7ffdefe).

Initially the error stopped the app at this line where I add in the background music (which doesn't make any sense to me because this line is also within one of the other scenes with no SKPhysicsContactDelegate and yet it runs smoothly):

   var backgroundMusicURL: NSURL = NSBundle.mainBundle().URLForResource("LevelOne", withExtension: "wav")!

When I commented out the background music the app then crashed at this line

   NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("addPlay"), name: "AddPlay", object: nil)

After I comment it out again the error jumps to this line

    narrow.physicsBody?.mass = 0.0001

then this

     narrow.physicsBody?.allowsRotation = true

and the error keeps moving as I comment out any lines that it previously crashed at. The app stops crashing once I remove the background music and all the functions that I call into my didMoveToView(view: SKView) that adds or modifies new or existing spritenodes, an example of one of these functions is below:

func addDiamond() {



    var diamond = SKSpriteNode(texture: diamondTexture)




    diamond.name = "diamond"
    diamond.physicsBody = SKPhysicsBody(circleOfRadius: diamond.size.width/2)
    diamond.zPosition = 1
    diamond.physicsBody?.mass = 0.01
    diamond.physicsBody?.allowsRotation = true
    diamond.physicsBody?.dynamic = true
    diamond.physicsBody?.affectedByGravity = false

    diamond.setScale(0.75)

    diamond.physicsBody?.categoryBitMask = diamondCategory
    diamond.physicsBody?.contactTestBitMask = laserCategory
    diamond.physicsBody?.collisionBitMask = laserCategory






    // setting the position 

    let minX = diamond.size.width/2
    let maxX = self.frame.size.width - diamond.size.width/2
    let rangeX = maxX - minX
    let positionX: CGFloat = round(CGFloat(arc4random()) % CGFloat(rangeX) + CGFloat(minX))

    let minY = self.frame.size.height/5
    let maxY = self.frame.size.height * 0.4
    let rangeY = maxY - minY
    let positionY: CGFloat = round(CGFloat(arc4random()) % CGFloat(rangeY) + CGFloat(minY))

    diamond.position = CGPointMake(positionX, positionY)

    // setting the rotation 

    let minR = 0
    let maxR = 6
    let rangeR = maxR - minR
    let positionR: CGFloat = round(CGFloat(arc4random()) % CGFloat(rangeR) + CGFloat(minR))
    diamond.zRotation = positionR
    // set animation

    let hold = SKAction.waitForDuration(4)
    let remove = SKAction.removeFromParent()

    diamond.runAction(SKAction.sequence([hold,remove]))



    // animation of bubble

    let minDur = 6
    let maxDur = 8
    let rangeDur = maxDur - minDur
    let durationOne = Int(arc4random()) % Int(rangeDur) + Int(minDur)
    let durOne = NSTimeInterval((Double(durationOne)/25))


    var animateArray:NSMutableArray = NSMutableArray()
    for i in 1...1500 {

        animateArray.addObject(SKAction.rotateByAngle(0.2, duration: 0.01))
      //animateArray.addObject(SKAction.rotateByAngle(-0.2, duration: 0.5))


    }


    diamond.runAction(SKAction.sequence(animateArray))
    animateArray.addObject(SKAction.removeFromParent())

     addChild(diamond)

}

this is added using the line below in the viewdidload

    diamondTimer = NSTimer.scheduledTimerWithTimeInterval(10, target: self, selector: Selector("addDiamond"), userInfo: nil, repeats: true) 

Scenes that do not use SKPhysicsContactDelegate run fine on the 4s. I also tested the 4s on the simulator and it seemingly crashes when you get to scenes using SKPhysicsContactDelegate but unlike the device an error doesn't come up, the device just blacks out and crashes without any debug sessions on xcode...does anyone have the faintest idea about what is going on here?


Solution

  • The problem was that I was using this line to place my nodes in a random position.

     let durationOne = Int(arc4random()) % Int(rangeDur) + Int(minDur)
    

    I suppose the problem with this line was that it in 32-bit devices (like the 4s) the device couldn't handle the size of the random number and it caused a crash. When I replaced that line with :

     let durationOne = UInt32(arc4random()) % UInt32(rangeDur) + UInt32(minDur)
    

    the problem stopped and the device ran smoothly. Although I have no idea why the error message did not target this line and kept moving about to irrelevant lines...anyway i hope that helps anyone with a similar problem!