0

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)]
}
BergQuester
  • 6,167
  • 27
  • 39
Benr783
  • 2,860
  • 4
  • 20
  • 28

2 Answers2

2

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.

Nate Cook
  • 92,417
  • 32
  • 217
  • 178
  • Option 2 fixes the crashes. Although, it still does not change the image every second. What is wrong with my code causing that not to work? – Benr783 Jun 14 '14 at 02:32
  • Add a `println(imageNumber)` after you generate it. Random doesn't mean nonrepeating - it's not uncommon to have several of the same numbers in a row if you wait long enough. – Nate Cook Jun 14 '14 at 02:33
  • you can skip one if you get a repeat – Grady Player Jun 14 '14 at 02:36
  • Still doesn't change with `func changeDot() { println("the images should be changing...") var theRandomImages: UIImage[] = [dotOne, dotTwo, dotThree, dotFour, dotFive, dotSix, dotSeven, dotEight, dotNine, dotTen, dotEleven, dotTwelve, dotThirteen] imageNumber = Int(arc4random_uniform(13)) openingScreenDynamicDot = theRandomImages[(imageNumber)] }` @NateCook – Benr783 Jun 14 '14 at 02:38
  • You'd need to update your `UIImageView` with the new image, and I don't see where in `viewDidLoad()` that you added the `UIImageView` to your view controller's view hierarchy. – Nate Cook Jun 14 '14 at 02:40
  • I made the UIImageView in my viewDidLoad, how can I access it as if it is global @NateCook – Benr783 Jun 14 '14 at 02:53
  • Declaring it inside your class definition, but outside any method, will make it an instance variable, or stored property - you can [read more here](https://developer.apple.com/library/prerelease/ios/documentation/swift/conceptual/swift_programming_language/Properties.html). – Nate Cook Jun 14 '14 at 03:36
  • Declare it like this: `var finalChangingDotWelcomePage: UIImageView!` and set it up just as you are in `viewDidLoad()` (but remove the `let`). Then call `self.view.addSubview(finalChangingDotWelcomePage)`. – Nate Cook Jun 14 '14 at 03:38
1

I was having similar mysterious crashes with arc4random() and resolved it by switching to arc4random_uniform().

Try this:

imageNumber = Int(arc4random_uniform(13))
GRiker
  • 86
  • 4