Here is my code (largeAsteroids.count is never 0):
var largeAsteroids=[[SKTexture]]()
func randomLargeAsteroidTextures()->Array<SKTexture>{
let i=Int(arc4random())%largeAsteroids.count
return largeAsteroids[i]// this line triggers EXC_BREAKPOINT
}
When I execute my code, I receive no errors but I get a EXC_BREAKPOINT. I ensured there wasn't any breakpoint and at index i there was a valid object.
First I changed SKTexture to AnyObject, it didn't help. Then I tried to use NSMutableArray instead of swift array, problem still exist:
var largeAsteroids=NSMutableArray()
func randomLargeAsteroidTextures()->AnyObject{
let i=Int(arc4random())%largeAsteroids.count
return largeAsteroids.objectAtIndex(i) // this line triggers EXC_BREAKPOINT
}
update:
Problem solved, replace:
let i=Int(arc4random())%largeAsteroids.count
by:
let i=Int(arc4random_uniform(UInt32(largeAsteroids.count)))
Thanks for Matt's solution:
You should probably be using arc4random_uniform. You'll get modulo bias from your current implementation. – Matt Gibson
You were running on a 32-bit target, yes? On a 32-bit target (e.g. iPhone 4), Swift Ints are 32-bits, and signed. However, on any platform, arc4random() returns a 32-bit unsigned integer.
Because of this conflict, and your conversion to Int, Int(arc4random())
, sometimes—in fact, half the time, all else being equal—your number was negative, giving you a negative array index, and causing your problem (though I get EXC_BAD_INSTRUCTION, as I'd expect, when I reproduce the problem; presumably you have a breakpoint set for exceptions?)
My suggestion, to use arc4random_uniform, should work fine as long as the count of your asteroids is never more than Int.max on a 32-bit platform, which is presumably quite unlikely, unless you're giving your gamer a really hard time. It will also avoid modulo bias in the random generation, so your resulting random numbers will be more uniformly distributed than in your original solution.