VAPOR 3: Learn Server-Side Swift with hands-on projects >>

How to generate random numbers in Swift 4.2 and later

Paul Hudson    May 16th 2018    @twostraws

Swift 4.2 implements SE-0202: Random Unification, which introduces a new random API that’s native to Swift. This means you can for the most part stop using arc4random_uniform() and GameplayKit to get randomness, and instead rely on a cryptographically secure randomizer that’s baked right into the core of the language.

  • Note: At the time of writing SE-0202 is only available in the latest Swift 4.2 toolchain snapshots from https://swift.org/download.

Let’s dive in with one of the most common use cases for randomness: generating random numbers. This is done by calling the random() method on whatever numeric type you want, providing the range you want to work with. For example, this generates a random number in the range 1 through 4, inclusive on both sides:

let randomInt = Int.random(in: 1..<5)

Similar methods exist for Float, Double, and CGFloat:

let randomFloat = Float.random(in: 1..<10)
let randomDouble = Double.random(in: 1...100)
let randomCGFloat = CGFloat.random(in: 1...1000)

There’s even one for booleans, generating either true or false randomly:

let randomBool = Bool.random()

Checking a random boolean is effectively the same as checking Int.random(in: 0...1) == 1, but it expresses your intent more clearly.

Best of all, SE-0202 includes support for shuffling arrays. Previously I used GameplayKit for this, partly because it was easier than teaching newbies how to shuffle arrays well, and partly because GameplayKit has a number of advanced shuffling algorithms that let you shape your data.

However, GameplayKit’s shuffling implementation is imported really poorly into Swift: you need to typecast your Swift array to an NSArray then force-cast the result back to your original type, like this:

let numbers = [1, 2, 3]
let shuffledNumbers = (numbers as NSArray).shuffled() as! [Int]

This is something I have complained about extensively on previous occasions – I even managed to get a screenshot of my Radar on this issue used as part of a 9to5mac article in the hope that someone from Apple would notice and fix the issue.

Well, at last the problem is being tackled head on: Swift 4.2 adds new shuffle() and shuffled() methods to arrays, depending on whether you want in-place shuffling or not. For example:

var albums = ["Red", "1989", "Reputation"]

// shuffle in place
albums.shuffle()

// get a shuffled array back
let shuffled = albums.shuffled()

It also adds a new randomElement() method to arrays, which returns one random element from the array if it isn’t empty, or nil otherwise:

if let random = albums.randomElement() {
    print("The random album is \(random).")
}

Having such a simple and secure random API built right into the core of our language is guaranteed to help many developers write better code, and it’s a really welcome feature.

The implementation of SE-0202 doesn’t mean things like GameplayKit are redundant, though – Swift only has one random number generator at its core, whereas GameplayKit supports more advanced functionality such as Gaussian distribution and “fair” randomnmess.

That being said, we are given the ability to implement our own random number generators to work alongside all the methods listed above, so it’s possible we might see some open source projects step in to fill the void.

 

MASTER SWIFT NOW
Buy Pro Swift Buy Swift Design Patterns Buy Practical iOS 11 Buy Swift Coding Challenges Buy Server-Side Swift (Vapor Edition) Buy Server-Side Swift (Kitura Edition) Buy Hacking with macOS Buy Advanced iOS Volume One Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with Swift Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

About the author

Paul Hudson is the creator of Hacking with Swift, the most comprehensive series of Swift books in the world. He's also the editor of Swift Developer News, the maintainer of the Swift Knowledge Base, and Mario Kart world champion. OK, so that last part isn't true. If you're curious you can learn more here.

Was this page useful? Let me know!

Click here to visit the Hacking with Swift store >>