Ben Dodson

Freelance iOS, Apple Watch, and Apple TV Developer

Generating a random colour, with a seed, in Swift 3

I’ve been working on some iOS 10 updates to Pocket Rocket1 which led me to trying to solve an interesting problem; how do you generate a random colour, with a seed, in Swift? The reason for this dilemma is that I’m going to start showing a grid view of Pocket articles and many of them do not have images associated with them. In order to break things up, I decided I’d like a random colour for the background of each article:

As each article is UICollectionViewCell, setting a random background colour is not suitable as when you scroll and the cells are re-used the backgrounds will change. Whilst that could be fixed fairly easily, I also want the colours to persist with the article between app launches and also be the same in the iPad app and the iMessage extension. This means I need to generate a random colour with a seed so that colours generated with the same seed will always be the same.

Thankfully this is fairly easy if we use the srand48 and drand48 functions:

func randomColor(seed: String) -> UIColor {
    
    var total: Int = 0
    for u in seed.unicodeScalars {
        total += Int(UInt32(u))
    }
    
    srand48(total * 200)
    let r = CGFloat(drand48())
    
    srand48(total)
    let g = CGFloat(drand48())
    
    srand48(total / 200)
    let b = CGFloat(drand48())
    
    return UIColor(red: r, green: g, blue: b, alpha: 1)
}

We start by taking a string (in my case an article title) and turning it into an integer by getting the sum of the unicode scalar values of each character. Next, we seed the drand48 function by using srand48 with our Int along with a multiplier or division so that the red, green, and blue values are all different. Finally, we compile the UIColor together.

I’ve put together a Swift Playground demonstrating this using the last few headlines from Daring Fireball:

As you can see, each article title results in a different colour; the same string will always result in the same colour being generated. Be aware that this is not collision free as it is just a basic addition of scalar values – a string such as “ben” and “neb” will result in the same colours. This isn’t an issue for my usage and still serves as an interesting way of seeding random colours.

  1. Specifically an iMessage app↩︎

Pocket Rocket for iOS 10 (now with an iMessage app) » « Tips for Remote Working