Search code examples
iosswiftnstimerarc4random

App crashes after arc4random() with timer?


In Swift, I have a timer. Every one second, the dot on the screen changes to a different dot image. It picks the dot that shows randomly. That is what I want. The app crashes right when it is launched. Like, immediately. How is this crashing fixed? And also, after that, will it work with my current code? After commenting out some stuff, and testing, the line that is causing it is imageNumber = Int(arc4random())%13 . How is this fixed?

My code is as follows:

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    var dotChangingTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("changeDot"), userInfo: nil, repeats: true)

    var theRandomImages: UIImage[] = [dotOne, dotTwo, dotThree, dotFour, dotFive, dotSix, dotSeven, dotEight, dotNine, dotTen, dotEleven, dotTwelve, dotThirteen]

    openingScreenDynamicDot = theRandomImages[Int(imageNumber)]
    let finalChangingDotWelcomePage = UIImageView(image: openingScreenDynamicDot)
    finalChangingDotWelcomePage.frame = CGRectMake(110, 234, 100, 100)
}
func changeDot() {
    println("the images should be changing...")
    imageNumber = Int(arc4random())%13

    var theRandomImages: UIImage[] = [dotOne, dotTwo, dotThree, dotFour, dotFive, dotSix, dotSeven, dotEight, dotNine, dotTen, dotEleven, dotTwelve, dotThirteen]

    openingScreenDynamicDot = theRandomImages[(imageNumber)]
}

Solution

  • You're getting those crashes because you're trying to cast a UInt32 value to Int, without regards to checking the range. Since UInt32 is unsigned, half of the possible return values to arc4random() will be outside the range of Int, and you'll get a runtime error when you attempt the cast. The safe way to do what you're doing is to take the modulo sum first, then cast to Int:

    imageNumber = Int(arc4random() % 13)
    

    However, this introduces modulo bias, which impacts the randomness of the result, so you'd be better off with:

    imageNumber = Int(arc4random_uniform(13))
    

    Both of these methods will give you random values between 0 and 12, inclusive.