Written by Brightec Team
Sep 27, 2013

How to change the colour of a UITextField's placeholder text for iOS7 and still support iOS6

Working with UITextFields is generally quite easy, but how do we change colour?

Placeholder text colour

Working with UITextFields is generally quite easy, you can customise most attributes apart from the placeholder text, while you can obviously change the text you can't change the colour of the text or it's position.

This was a problem we had on a recent project, our design required us to have UITextFields with black backgrounds, the placeholder text colour is dark grey which is almost invisible in our app and Apple provides no easy way to change this.

The solution

We solved this by subclassing UITextField and overriding drawPlaceholderInRect: method to draw our own placeholder text. This is fairly straight forward in iOS6 but did not work as expected in iOS 7.

- (void)drawPlaceholderInRect:(CGRect)rect
    UIColor *colour = [UIColor lightGrayColor];
    if ([self.placeholder respondsToSelector:@selector(drawInRect:withAttributes:)]) {
        // iOS7 and later
        NSDictionary *attributes = @{NSForegroundColorAttributeName: colour, NSFontAttributeName: self.font};
        CGRect boundingRect = [self.placeholder boundingRectWithSize:rect.size options:0 attributes:attributes context:nil];
        [self.placeholder drawAtPoint:CGPointMake(0, (rect.size.height/2)-boundingRect.size.height/2) withAttributes:attributes];
    else {
        // iOS 6
        [colour setFill];
        [self.placeholder drawInRect:rect withFont:self.font lineBreakMode:NSLineBreakByTruncatingTail alignment:self.textAlignment];

Let's walk through the code above. First thing we do is create the variable colour which is the colour that we want our placeholder text to be. We then create an if statement that branches out logic so we can handle drawing the placeholder text differently for iSO6 and iOS7 (and later).

We did this because iOS6's NSString drawInRect:withFont:lineBreakMode:alignment method is deprecated in iOS7 and does not display correctly. Looking at the iOS7 code we create an attributes dictionary with two entires, one that sets the text colour and the other sets the font colour.

To center the text vertically within the UITextField we need to calculate the height of the text, again in iOS7 the NSString sizeWithFont:constrainedToSize:lineBreakMode: has been deprecated so we use the new method boundingRectWithSize:options:attributes:context: method to calculate the size of the bounded box that is needed to fit the label on one line, for more information see: https://developer.apple.com/library/ios/documentation/UIKit/Reference/NSString_UIKit_Additions/....

Now that we've calculated the size of the text we can use new iOS7 method drawAtPoint:withAttributes: to draw the text at a specified point. In this case we want to draw the text from the left of the UITextField so we set the x coordinate to zero and we want to draw the text in the middle of the UITextField so we set the y coordinate to the vertical center minus half of the calculated text height.

Now for iOS 6 it's a bit simpler we just call the setFill method on the colour that we created earlier which sets the colour used for subsequent drawing operations. We then just call the method NSString drawInRect:withFont:lineBreakMode:alignment to draw the text within the rect of the UITextField which will also vertically center the text.

And that's it we now have changed the colour of the placeholder text in both iOS6 and iOS7.

This article was originally written for Brightec by Cameron Cooke