Having a bug in your code is never fun, but having a bug in your iOS game or app is even worse. You can’t just quickly fix it and hope nobody noticed. Your game has to go through Apple’s review process again, which takes time. Having a bug in your game just a couple of days before Christmas, can spoil your Christmas joy instantly. Apple is having a week off, meaning your bug will be in there for at least 2 weeks. The following Integer Overflow made me be angry at myself (and at Apple a bit). Don’t let it ruin your life.
Let’s get it over with. What caused me so much frustration. This was the line of code that caused a crash occasionally.
let randomIndex = Int(arc4random()) % self.count
I extended the Set class with a function to return a random element from the Set.
Why does this line of code let your game crash at runtime?
The function arc4random() returns a UInt32, a number in the range of 0 to 2^32. Now, what is the size of an Int in Swift? It depends. It depends on the hardware you run on. On 32-bit devices (iPad, iPhone 4S, iPhone 5), an Int is stored in 32-bits, so it ranges from -2^31+1 to +2^31-1. On 64-bit devices an Int is 64 bits. Therefore the return value from arc4random() is potentially bigger than can be represented by an Int. And by design the Swift programming language does not truncate bits but throws an exception.
Why am I angry at myself?
I have over 600 automated tests covering all my game logic, even this line of code, but I only ran my tests on 64-bit devices in the simulator.
Why am I angry at Apple?
How is it possible that Int has an initializer that potentially causes your app or game to crash runtime? In my opinion this should be handled at compile time. It should not be possible to initialize an Int with a bigger number.
The solution is simple, just rewrite the line like this:
let randomIndex = Int(arc4random_uniform(UInt32(self.count)))
arc4random_uniform() will return a uniformly distributed random number less than the provided upper_bound.
If I helped you with my article or if you have any questions, let me know.