Xcode

When coding for iOS, I usually style images with shadows so the layout looks more elegant. Adding shadows is easy, but when it comes to adding borders to UIImageViews things become trickier. That’s because when adding a border to a UIImageView, this border hides info from the image. To solve this issue, we have to rescale the image and then add the border to the scaled image.

Let’s do how can we do it by extending UIImageView class (it’s object oriented programming, so it is nice to have reusable classes, isn’t it?). First, we have to create a new Objective-C class. We name our class UIImageViewAddBorder.h and .m accordingly. In UIImageViewAddBorder.h, we define our interface as shown below:

#import <Foundation/Foundation.h>;

@interface UIImageView (ImageViewBorder)

-(void)setImage:(UIImage*)image borderWidth:(CGFloat)borderWidth;

@end

This functions receives as input an image with border width. Now lets fill the implementation file. In our .m file we need a function to scale down the image. This method should look like this one:

-(UIImage*)scaleDownImage:(UIImage*)image{
UIImage* scaledDownImage = image;

CALayer* layer = self.layer;
CGFloat borderWidth = layer.borderWidth;

if (borderWidth > 0)
{
CGRect newRect = CGRectMake(0.0, 0.0, self.bounds.size.width - 2 * borderWidth, self.bounds.size.height - 2 *borderWidth);

if (image.size.height > newRect.size.height || image.size.width > newRect.size.width)
{
UIGraphicsBeginImageContext(newRect.size);
[image drawInRect:newRect];
scaledDownImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
}
return scaledDownImage;
}

This function gets the original image, calculates a new rectangle (the original minus the border width) in which the new image should fill in, scales down the image and returns the scaled image.

Adding the border in the image can be done with the code below. This snippet is pretty self explanatory.

-(void)addImageViewBorder:(CGFloat)borderWidth
{
CALayer* layer = [self layer];
[layer setBackgroundColor:[UIColor grayColor].CGColor];
[layer setBorderWidth:borderWidth];
[self setContentMode:UIViewContentModeCenter];
self.clipsToBounds = YES;
[layer setBorderColor:[UIColor whiteColor].CGColor];
[layer setShadowColor:[UIColor blackColor].CGColor];
layer.shadowOpacity = 0.6;
layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
layer.shadowRadius = 5.0f;

}

Finally we implement the public method that calls the rescale and border methods as follows:

-(void)setImage:(UIImage*)image borderWidth:(CGFloat)borderWidth
{
[self addImageViewBorder:borderWidth];
UIImage* scaledDownImage = [self scaleDownImage:image];
self.image = scaledDownImage;
}

Now it is time to test what we have done. You can just create a ViewController, import UIImageViewAddBorder.h, and call the following to any UIImageView you want to apply a border:

[myImageView setImage:myImage borderWidth:3.0];

where “myImageView” is the name of your UIImageView.

I made the class available on Github with an example implementation, so feel free to check it out  here.