When your UX designer gives you a palette of Hexadecimal colors to assign at random to each user in the contact list and you already know that this color palette may change in the future, you start by breaking the problem into small parts.
Hexadecimal strings
Let’s assume that you load your Hex colors as strings from some file (in plain text with separators or in a JSON) and put them in an array.
0 1 2 |
NSMutableArray *arrayOfHexColorStrings; |
Hex color in #FFFFFF
format is in fact a 0xFFFFFF
hexadecimal integer. So, the general idea behind the following code is to transform hexadecimal represented string value into an unsigned integer. In this way you can also reuse it in the other part of your code to more general purposes. The best way to do it is using NSScanner
class and the corresponding scanHexInt:
method.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
+ (NSArray *)getHexNumbersFromHexStrings:(NSArray *)aStrings { // Initialize array with capacity of array of hex strings NSMutableArray *arrayOfHexNumbers = [NSMutableArray arrayWithCapacity:[aStrings count]]; // Loop through all hex strings for (NSString *hexString in aStrings) { // Initialize result NSUInteger result = 0; // Initialize scanner with current hex string NSScanner *scanner = [NSScanner scannerWithString:hexString]; // Eventually skip the hash (#) character scanner.charactersToBeSkipped = [NSCharacterSet characterSetWithCharactersInString:@"#"]; // If the scanner found a valid hexadecimal representation add its result to array if ([scanner scanHexInt:&result]) [arrayOfHexNumbers addObject:@(result)]; } // Return the array return arrayOfHexNumbers; } |
As per documentation “The hexadecimal integer representation may optionally be preceded by 0x or 0X” we don’t need to check for 0x or 0X preceding the strings because scanHexInt:
will do it for us and skip them automatically.
Returning result of this function is an NSArray
with all you hex integer numbers converted from respective strings.
Random color from array
We must assign a random color to each contact, but to be associated and recognized by the user it must be the same for each application launch. We can surely generate a random number and save it somewhere in DB alongside contact data, but why complicate it so much if we can directly use contact data to do this?
0 1 2 3 4 5 6 7 8 9 10 11 |
// Use contacts name and surname to generate a hash NSUInteger nameSurnameHash = [aNameSurname hash]; // Use modulo to get the integer remainder of division by colors in our palette, // which will be index to use later NSUInteger colorNumber = nameSurnameHash % [arrayOfHexNumbers count]; // Get the unsigned integer value from NSNumber at given index NSUInteger colorInteger = [arrayOfHexNumbers[colorNumber] unsignedIntegerValue]; |
For exercise wrap it in a function that receives a string to hash with the array of hex numbers and as a result return a hex integer.
Get the UIColor
The final step is to convert our hexadecimal color integer that we choose randomly into a valid UIColor. To do this you can write a dedicated function or #defin
e a simple macro
0 1 2 3 4 5 6 7 8 |
#define UIColorFromRGB(rgb) NSUIColorFromRGBA(rgb, 255) #define UIColorFromRGBA(rgb, a) [NSUIColor colorWithRed:((float)((rgb & 0xFF0000) >> 16))/255.0 \ green:((float)((rgb & 0x00FF00) >> 8))/255.0 \ blue:((float)((rgb & 0x0000FF) >> 0))/255.0 \ alpha:((float)a)/255.0] |
And use it like this
0 1 2 |
UIColor *color = UIColorFromRGB(colorInteger); |
or the full UIColorFromRGBA
and specify also the desired Alpha value in [0, 255]
range.