High performance shadows for UIView
Published on: July 8, 2015No app is truly complete without some subtle shadows. Especially now that Google's Material Design is showing us that shadows are cool again we need a way to properly add them in our apps. In my previous post I wrote about a way to create a custom UICollectionView layout. There was one problem with that post though, that shadows are incredibly heavy on the iPhone and scrolling stutters.
So can we fix this? The answer is yes and the solution is (surprisingly) easy. A Google search led me to this Stackoverflow question about shadows. The solution I tried first was to simple rasterize my layer but that wasn't what I was looking for. Images started to look very bad and I didn't want that. Another solution that was proposed is to supply the layer with a shadowPath.
What is shadowPath and what does it do?
If you set the shadowPath property it will function as a guide to the shadow that ends up underneath your view. If you don't set this, the view need to be analyzed at runtime to determine where the view is transparent and where it isn't which will result in the eventual shadow shape. This is a pretty costly operation, especially if you do this for about 20 views at a time in a UICollectionView. And even more so if you start scrolling in this view.
Implementing shadowPath
Assuming we're using the code from my previous post there isn't much we have to do. We have to create a circular path that has the same size as the imageView. We know that our imageView get's rendered at 80px by 80px so we can use UIBezierPath with rounded corners to generate a circular path. Let's add this line before we specify the shadows in the CustomCollectionViewCell class:
layer.shadowPath = UIBezierPath(roundedRect: CGRectMake(0, 0, 80, 80), cornerRadius: 40).CGPath
Build and run the project and you should now see butter smooth scrolling instead of the bad scrolling we had before.
Summary
If you want to use shadows on your views then you should probably also set the shadowPath on your view to ensure proper performance. By doing this you can speed up rendering a great deal because otherwise the view will be analyzed at runtime to find out what shape the view has, this is a lot slower than just providing the proper shadow path. Setting the path does not only increase performance but it also allows you to create many fun effects with shadows.