398

In the Music app of the new iOS, we can see an album cover behind a view that blurs it.

How can something like that be accomplished? I've read the documentation, but did not find anything there.

jscs
  • 63,694
  • 13
  • 151
  • 195
kondratyevdev
  • 3,569
  • 3
  • 13
  • 11

25 Answers25

594

You can use UIVisualEffectView to achieve this effect. This is a native API that has been fine-tuned for performance and great battery life, plus it's easy to implement.

Swift:

//only apply the blur if the user hasn't disabled transparency effects
if !UIAccessibility.isReduceTransparencyEnabled {
    view.backgroundColor = .clear

    let blurEffect = UIBlurEffect(style: .dark)
    let blurEffectView = UIVisualEffectView(effect: blurEffect)
    //always fill the view
    blurEffectView.frame = self.view.bounds
    blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

    view.addSubview(blurEffectView) //if you have more UIViews, use an insertSubview API to place it where needed
} else {
    view.backgroundColor = .black
}

Objective-C:

//only apply the blur if the user hasn't disabled transparency effects
if (!UIAccessibilityIsReduceTransparencyEnabled()) {
    self.view.backgroundColor = [UIColor clearColor];

    UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
    UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
    //always fill the view
    blurEffectView.frame = self.view.bounds;
    blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    [self.view addSubview:blurEffectView]; //if you have more UIViews, use an insertSubview API to place it where needed
} else {
    self.view.backgroundColor = [UIColor blackColor];
}

If you are presenting this view controller modally to blur the underlying content, you'll need to set the modal presentation style to Over Current Context and set the background color to clear to ensure the underlying view controller will remain visible once this is presented overtop.

Eric
  • 16,003
  • 15
  • 87
  • 139
Jordan H
  • 52,571
  • 37
  • 201
  • 351
  • Awesome! @Joey can I apply this to Sprite Kit? Lets say when the game is paused. – Adnan Zahid Feb 20 '15 at 09:03
  • 9
    As a clarification to the `insertSubView:belowSubView:` comment in this code, I have used the following to set the blur as the background of the view: `view.insertSubview(blurEffectView, atIndex: 0)` – Michael Voccola Apr 06 '15 at 22:52
  • @Joey is it possible to subclass `UIVisualEffectView` and then simply treat it similar to an `UIView`? – borchero Apr 08 '15 at 14:46
  • 1
    requires update for swift part to version 2.0 :) or indicate the answer's version of swift – Julian Aug 07 '15 at 14:46
  • For Swift 2.0 check this out: [Swift 2.0 code](http://stackoverflow.com/a/38766868/5280107) – RaptoX Aug 04 '16 at 12:07
  • 3
    With reference to the above answer, Is it necessary to check "if (!UIAccessibilityIsReduceTransparencyEnabled())" or Can we skip that? – GKK Sep 14 '16 at 14:28
  • 3
    If you are presenting your view controller, make sure you change modalPresentationStyle = .overCurrentContext along with setting background color as clear – Shardul Oct 30 '16 at 07:54
  • 3
    Works Awesome !!! Need single Change : [self.view insertSubview:blurEffectView atIndex:1]; – Abhishek Thapliyal Jan 10 '17 at 07:41
  • 3
    In iOS 11, I'm finding it's not necessary to manually check `UIAccessibilityIsReduceTransparencyEnabled()`. – Nate Whittaker Apr 03 '18 at 19:55
  • Thank you very much! It's a cool way using Apple's native classes – alones Aug 06 '18 at 23:28
  • 1
    +1 for the frame line, and +2 for accessibility, but I had to replace insert with `view.insertSubview(blurEffectView, at: 0)` in order to not blur an image that I placed on a blurred background. –  Dec 24 '18 at 05:05
  • 1
    Do you know how to why if I call my blurEffect like this: ```navigationController?.pushViewController(vc, animated: true)``` it's going to make the blur and then go away? and still using ```vc.modalPresentationStyle = .overCurrentContext```. Any thoughts will be appreciated. – Marlhex Apr 16 '19 at 11:59
  • how would you remove the blur effect? I tried ```blurEffectView.removeFromSuperView()``` and it was not removed – Noah Iarrobino Jan 04 '21 at 05:01
289

Core Image

Since that image in the screenshot is static, you could use CIGaussianBlur from Core Image (requires iOS 6). Here is sample: https://github.com/evanwdavis/Fun-with-Masks/blob/master/Fun%20with%20Masks/EWDBlurExampleVC.m

Mind you, this is slower than the other options on this page.

#import <QuartzCore/QuartzCore.h>

- (UIImage*) blur:(UIImage*)theImage
{   
    // ***********If you need re-orienting (e.g. trying to blur a photo taken from the device camera front facing camera in portrait mode)
    // theImage = [self reOrientIfNeeded:theImage];

    // create our blurred image
    CIContext *context = [CIContext contextWithOptions:nil];
    CIImage *inputImage = [CIImage imageWithCGImage:theImage.CGImage];

    // setting up Gaussian Blur (we could use one of many filters offered by Core Image)
    CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"];
    [filter setValue:inputImage forKey:kCIInputImageKey];
    [filter setValue:[NSNumber numberWithFloat:15.0f] forKey:@"inputRadius"];
    CIImage *result = [filter valueForKey:kCIOutputImageKey];

    // CIGaussianBlur has a tendency to shrink the image a little, 
    // this ensures it matches up exactly to the bounds of our original image
    CGImageRef cgImage = [context createCGImage:result fromRect:[inputImage extent]];

    UIImage *returnImage = [UIImage imageWithCGImage:cgImage];//create a UIImage for this function to "return" so that ARC can manage the memory of the blur... ARC can't manage CGImageRefs so we need to release it before this function "returns" and ends.
    CGImageRelease(cgImage);//release CGImageRef because ARC doesn't manage this on its own.

    return returnImage;

    // *************** if you need scaling
    // return [[self class] scaleIfNeeded:cgImage];
}

+(UIImage*) scaleIfNeeded:(CGImageRef)cgimg {
    bool isRetina = [[[UIDevice currentDevice] systemVersion] intValue] >= 4 && [[UIScreen mainScreen] scale] == 2.0;
    if (isRetina) {
        return [UIImage imageWithCGImage:cgimg scale:2.0 orientation:UIImageOrientationUp];
    } else {
        return [UIImage imageWithCGImage:cgimg];
    }
}

- (UIImage*) reOrientIfNeeded:(UIImage*)theImage{

    if (theImage.imageOrientation != UIImageOrientationUp) {

        CGAffineTransform reOrient = CGAffineTransformIdentity;
        switch (theImage.imageOrientation) {
            case UIImageOrientationDown:
            case UIImageOrientationDownMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, theImage.size.width, theImage.size.height);
                reOrient = CGAffineTransformRotate(reOrient, M_PI);
                break;
            case UIImageOrientationLeft:
            case UIImageOrientationLeftMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, theImage.size.width, 0);
                reOrient = CGAffineTransformRotate(reOrient, M_PI_2);
                break;
            case UIImageOrientationRight:
            case UIImageOrientationRightMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, 0, theImage.size.height);
                reOrient = CGAffineTransformRotate(reOrient, -M_PI_2);
                break;
            case UIImageOrientationUp:
            case UIImageOrientationUpMirrored:
                break;
        }

        switch (theImage.imageOrientation) {
            case UIImageOrientationUpMirrored:
            case UIImageOrientationDownMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, theImage.size.width, 0);
                reOrient = CGAffineTransformScale(reOrient, -1, 1);
                break;
            case UIImageOrientationLeftMirrored:
            case UIImageOrientationRightMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, theImage.size.height, 0);
                reOrient = CGAffineTransformScale(reOrient, -1, 1);
                break;
            case UIImageOrientationUp:
            case UIImageOrientationDown:
            case UIImageOrientationLeft:
            case UIImageOrientationRight:
                break;
        }

        CGContextRef myContext = CGBitmapContextCreate(NULL, theImage.size.width, theImage.size.height, CGImageGetBitsPerComponent(theImage.CGImage), 0, CGImageGetColorSpace(theImage.CGImage), CGImageGetBitmapInfo(theImage.CGImage));

        CGContextConcatCTM(myContext, reOrient);

        switch (theImage.imageOrientation) {
            case UIImageOrientationLeft:
            case UIImageOrientationLeftMirrored:
            case UIImageOrientationRight:
            case UIImageOrientationRightMirrored:
                CGContextDrawImage(myContext, CGRectMake(0,0,theImage.size.height,theImage.size.width), theImage.CGImage);
                break;

            default:
                CGContextDrawImage(myContext, CGRectMake(0,0,theImage.size.width,theImage.size.height), theImage.CGImage);
                break;
        }

        CGImageRef CGImg = CGBitmapContextCreateImage(myContext);
        theImage = [UIImage imageWithCGImage:CGImg];

        CGImageRelease(CGImg);
        CGContextRelease(myContext);
    }

    return theImage;
}

Stack blur (Box + Gaussian)

  • StackBlur This implements a mix of Box and Gaussian blur. 7x faster than non accelerated gaussian, but not so ugly as box blur. See a demo in here (Java plugin version) or here (JavaScript version). This algorithm is used in KDE and Camera+ and others. It doesn't use the Accelerate Framework but it's fast.

Accelerate Framework

  • In the session “Implementing Engaging UI on iOS” from WWDC 2013 Apple explains how to create a blurred background (at 14:30), and mentions a method applyLightEffect implemented in the sample code using Accelerate.framework.

  • GPUImage uses OpenGL shaders to create dynamic blurs. It has several types of blur: GPUImageBoxBlurFilter, GPUImageFastBlurFilter, GaussianSelectiveBlur, GPUImageGaussianBlurFilter. There is even a GPUImageiOSBlurFilter that “should fully replicate the blur effect provided by iOS 7's control panel” (tweet, article). The article is detailed and informative.

    -(UIImage *)blurryGPUImage:(UIImage *)image withBlurLevel:(NSInteger)blur {
        GPUImageFastBlurFilter *blurFilter = [GPUImageFastBlurFilter new];
        blurFilter.blurSize = blur;
        UIImage *result = [blurFilter imageByFilteringImage:image];
        return result;
    }

Other stuff

Andy Matuschak said on Twitter: “you know, a lot of the places where it looks like we're doing it in real time, it's static with clever tricks.”

At doubleencore.com they say “we’ve found that a 10 pt blur radius plus a 10 pt increase in saturation best mimics iOS 7’s blur effect under most circumstances”.

A peek at the private headers of Apple's SBFProceduralWallpaperView.

Finally, this isn't a real blur, but remember you can set rasterizationScale to get a pixelated image: http://www.dimzzy.com/blog/2010/11/blur-effect-for-uiview/

George WS
  • 3,903
  • 5
  • 27
  • 39
Jano
  • 62,815
  • 21
  • 164
  • 192
  • Thanks for answer! One problem is solved. But we have one more problem. How to get cover image in iOS 7. If it possible? – kondratyevdev Jun 11 '13 at 10:37
  • If you mean how to get the background wallpaper image from your phone, no idea at this point. I didn't see that functionality in the [API diffs](https://developer.apple.com/library/prerelease/ios/releasenotes/General/iOS70APIDiffs/index.html). Maybe it uses a private API. – Jano Jun 11 '13 at 10:44
  • One thing I've noticed (and I could be totally wrong) is that Apple's blur appears to add in a little color saturation as well. So, I don't think it's a simple gaussian blur. – xtravar Jun 17 '13 at 04:50
  • Remember the scale factor when returning the `UIImage` otherwise it's going to look way too big on a Retina device... – Stephen Darlington Jul 27 '13 at 10:16
  • Do you know if such effect could be applied to a UITableViewCell without degrading performance ? – Leonardo Sep 01 '13 at 07:21
  • Just to be clear, as I was confused at first, applyLightEffect isn't from Accelerated framework. It is a method found in sample code from a WWDC 2013 session. You can find the code here (iOS_UIImageEffects.zip): https://developer.apple.com/downloads/index.action?name=WWDC%202013# – Perishable Dave Sep 26 '13 at 23:40
  • The code from indieambitions.com worked great for me. I changed line 62 to support images that have non-portrait orientations: ` UIImage *returnImage = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation];` – bugloaf Dec 09 '13 at 18:39
  • Actually iOS-Realtime-Blur suffers from the same issue as iOS-Blur: on iOS7 devices it just grabs a toolbar layer and doesn't use any of its own blurring code. So it stands a good chance of being rejected by apple also. – auibrian Apr 21 '14 at 03:31
18

Here's an easy way to add custom blur without haggling with private APIs using UIViewPropertyAnimator:

First, declare class property:

var blurAnimator: UIViewPropertyAnimator!

Then set your blur view in viewDidLoad():

let blurEffectView = UIVisualEffectView()
blurEffectView.backgroundColor = .clear
blurEffectView.frame = view.bounds
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(blurEffectView)

blurAnimator = UIViewPropertyAnimator(duration: 1, curve: .linear) { [blurEffectView] in
    blurEffectView.effect = UIBlurEffect(style: .light)
}

blurAnimator.fractionComplete = 0.15 // set the blur intensity.    

Note: This solution is not suitable for UICollectionView/UITableView cells

Adam Bardon
  • 3,829
  • 7
  • 38
  • 73
15

I decided to post a written Objective-C version from the accepted answer just to provide more options in this question..

- (UIView *)applyBlurToView:(UIView *)view withEffectStyle:(UIBlurEffectStyle)style andConstraints:(BOOL)addConstraints
{
  //only apply the blur if the user hasn't disabled transparency effects
  if(!UIAccessibilityIsReduceTransparencyEnabled())
  {
    UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:style];
    UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
    blurEffectView.frame = view.bounds;

    [view addSubview:blurEffectView];

    if(addConstraints)
    {
      //add auto layout constraints so that the blur fills the screen upon rotating device
      [blurEffectView setTranslatesAutoresizingMaskIntoConstraints:NO];

      [view addConstraint:[NSLayoutConstraint constraintWithItem:blurEffectView
                                                       attribute:NSLayoutAttributeTop
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:view
                                                       attribute:NSLayoutAttributeTop
                                                      multiplier:1
                                                        constant:0]];

      [view addConstraint:[NSLayoutConstraint constraintWithItem:blurEffectView
                                                       attribute:NSLayoutAttributeBottom
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:view
                                                       attribute:NSLayoutAttributeBottom
                                                      multiplier:1
                                                        constant:0]];

      [view addConstraint:[NSLayoutConstraint constraintWithItem:blurEffectView
                                                       attribute:NSLayoutAttributeLeading
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:view
                                                       attribute:NSLayoutAttributeLeading
                                                      multiplier:1
                                                        constant:0]];

      [view addConstraint:[NSLayoutConstraint constraintWithItem:blurEffectView
                                                       attribute:NSLayoutAttributeTrailing
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:view
                                                       attribute:NSLayoutAttributeTrailing
                                                      multiplier:1
                                                        constant:0]];
    }
  }
  else
  {
    view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.7];
  }

  return view;
}

The constraints could be removed if you want incase if you only support portrait mode or I just add a flag to this function to use them or not..

valbu17
  • 4,034
  • 3
  • 30
  • 41
  • 1
    for new folks (me), one way to call above method is: [self applyBlurToView:self.view withEffectStyle:UIBlurEffectStyleDark andConstraints:YES]; (thank you NorthBlast) – tmr Sep 10 '15 at 02:27
15

enter image description here

From Xcode you can do it easily. Follow the steps from xcode. Drag visual effect view on your uiview or imageview.

Happy Coding :)

Mehedi Hasan
  • 359
  • 3
  • 10
14

I don't think I'm allowed to post the code, but the above post mentioning the WWDC sample code is correct. Here is the link: https://developer.apple.com/downloads/index.action?name=WWDC%202013

The file you're looking for is the category on UIImage, and the method is applyLightEffect.

As I noted above in a comment, the Apple Blur has saturation and other things going on besides blur. A simple blur will not do... if you are looking to emulate their style.

pkamb
  • 33,281
  • 23
  • 160
  • 191
xtravar
  • 1,321
  • 11
  • 24
  • 8
    That link is broken. Here's the correct link: https://developer.apple.com/downloads/index.action?name=WWDC%202013 – olivaresF Aug 01 '13 at 23:53
  • Note that this example code requires XCode 5.0 and iOS SDK 7.0 (which haven't been publicly released yet) – Mike Gledhill Aug 22 '13 at 09:49
  • Thanks for the fixed link, however there's a few sample code in it, which one is containing the relevant UIImage category ? – Leonardo Sep 01 '13 at 07:19
  • At [doubleencore.com](http://www.doubleencore.com/2013/09/the-essential-ios-7-design-guide/) they say “we’ve found that a 10 pt blur radius plus a 10 pt increase in saturation best mimics iOS 7’s blur effect under most circumstances”. – Jano Sep 26 '13 at 19:58
  • 1
    @Leonardo iOS_RunningWithASnap.zip – John Starr Dewar Sep 27 '13 at 03:59
  • 1
    ...or iOS_UIImageEffects.zip is more specifically just this. – John Starr Dewar Sep 27 '13 at 05:16
10

Here's a fast implementation in Swift using CIGaussianBlur:

func blur(image image: UIImage) -> UIImage {
    let radius: CGFloat = 20;
    let context = CIContext(options: nil);
    let inputImage = CIImage(CGImage: image.CGImage!);
    let filter = CIFilter(name: "CIGaussianBlur");
    filter?.setValue(inputImage, forKey: kCIInputImageKey);
    filter?.setValue("\(radius)", forKey:kCIInputRadiusKey);
    let result = filter?.valueForKey(kCIOutputImageKey) as! CIImage;
    let rect = CGRectMake(radius * 2, radius * 2, image.size.width - radius * 4, image.size.height - radius * 4)
    let cgImage = context.createCGImage(result, fromRect: rect);
    let returnImage = UIImage(CGImage: cgImage);

    return returnImage;
}
kev
  • 7,712
  • 11
  • 30
  • 41
9

I think the easiest solution to this is to override UIToolbar, which blurs everything behind it in iOS 7. It's quite sneaky, but it's very simple for you to implement, and fast!

You can do it with any view, just make it a subclass of UIToolbar instead of UIView. You can even do it with a UIViewController's view property, for example...

1) create a new class that is a "Subclass of" UIViewController and check the box for "With XIB for user interface".

2) Select the View and go to the identity inspector in the right-hand panel (alt-command-3). Change the "Class" to UIToolbar. Now go to the attributes inspector (alt-command-4) and change the "Background" color to "Clear Color".

3) Add a subview to the main view and hook it up to an IBOutlet in your interface. Call it backgroundColorView. It will look something like this, as a private category in the implementation (.m) file.

@interface BlurExampleViewController ()
@property (weak, nonatomic) IBOutlet UIView *backgroundColorView;
@end

4) Go to the view controller implementation (.m) file and change the -viewDidLoad method, to look as follows:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.barStyle = UIBarStyleBlack; // this will give a black blur as in the original post
    self.backgroundColorView.opaque = NO;
    self.backgroundColorView.alpha = 0.5;
    self.backgroundColorView.backgroundColor = [UIColor colorWithWhite:0.3 alpha:1];
}

This will give you a dark gray view, which blurs everything behind it. No funny business, no slow core image blurring, using everything that is at your fingertips provided by the OS/SDK.

You can add this view controller's view to another view, as follows:

[self addChildViewController:self.blurViewController];
[self.view addSubview:self.blurViewController.view];
[self.blurViewController didMoveToParentViewController:self];

// animate the self.blurViewController into view

Let me know if anything is unclear, I'll be happy to help!


Edit

UIToolbar has been changed in 7.0.3 to give possibly-undesirable effect when using a coloured blur.

We used to be able to set the colour using barTintColor, but if you were doing this before, you will need to set the alpha component to less than 1. Otherwise your UIToolbar will be completely opaque colour - with no blur.

This can be achieved as follows: (bearing in mind self is a subclass of UIToolbar)

UIColor *color = [UIColor blueColor]; // for example
self.barTintColor = [color colorWithAlphaComponent:0.5];

This will give a blue-ish tint to the blurred view.

Sam
  • 5,892
  • 1
  • 25
  • 27
  • 1
    Not bad man. I used this three lines in my view: `self.backgroundColorView.opaque = NO;` `self.backgroundColorView.alpha = 0.5;` `self.backgroundColorView.backgroundColor = [UIColor colorWithWhite:0.3 alpha:1];`But the background doesn't been blurred, just make a nice over effect. thanks you anyway! – IgniteCoders Dec 12 '13 at 18:04
  • 1
    I'm not seeing any blurring at all using this technique. It just creates a colored overlay. – MusiGenesis Feb 02 '14 at 13:12
  • make sure the coloured overlay alpha is less than 1. You can use a UIToolbar without the view controller, which may be simpler depending on what you need. – Sam Feb 03 '14 at 13:41
  • neat trick man. I converted my view to UIToolbar class in the storyboard, then changed the view background to clear color. It gave a white blurred background. If you make alpha less than 1 the blurry effect will go away. – fullmoon Feb 28 '15 at 13:01
7

Custom blur scale

You can try UIVisualEffectView with custom setting as -

class BlurViewController: UIViewController {
    private let blurEffect = (NSClassFromString("_UICustomBlurEffect") as! UIBlurEffect.Type).init()

    override func viewDidLoad() {
        super.viewDidLoad()
        let blurView = UIVisualEffectView(frame: UIScreen.main.bounds)
        blurEffect.setValue(1, forKeyPath: "blurRadius")
        blurView.effect = blurEffect
        view.addSubview(blurView)
    }   
}

Output:- for blurEffect.setValue(1... & blurEffect.setValue(2.. enter image description here enter image description here

Jack
  • 13,571
  • 6
  • 76
  • 98
  • 4
    It will stop work if in next version of iOS name of this parameter is changed. – Ariel Bogdziewicz Jan 24 '19 at 13:40
  • @ArielBogdziewicz currently its working. i will update if there is any API variation in wwdc. – Jack Jan 31 '19 at 12:03
  • Ummm... nope, you never want to access private APIs. They're private for a reason. They will change, they will break, and/or Apple will reject your app. Use another method, there's plenty. Kudos for finding the hack, but, not recommended. – n13 Apr 04 '19 at 06:48
  • @Jack Thank you a lot for this answer! It's the only solution I found to my problem: blurring a view according to the position of another view. However, I still have another question. Is there a way I could add vibrancy on top of my UIBlurEffect? If so, how? Do I need to create another view for this on top of my blurView? I tried so but it always crashed when I used `(NSClassFromString("_UICustomVibrancyEffect") as! UIVibrancyEffect.Type).init()` Would really appreciate some help! – Moritz Apr 26 '19 at 23:12
  • @Moritz haven't tried. But it should work.you can try & check. – Jack Apr 27 '19 at 05:04
  • @Jack I realized I could just put a white UIView on top of my blurred view and change the alpha with a quick animation. In hindsight, I probably asked too soon, so my bad... sorry – Moritz Apr 28 '19 at 21:32
  • @Shaked any compiler error u encountered or runtime it doesn't reflect – Jack Aug 10 '20 at 13:32
  • Runtime - setValueForKeyPath crashes the app (in tvOS 14) – Shaked Sayag Aug 11 '20 at 14:57
  • On iOS14 this gives me a black and white unblurred view. – w0mbat Sep 20 '20 at 01:50
6

In case this helps anyone, here is a swift extension I created based on the answer by Jordan H. It is written in Swift 5 and can be used from Objective C.

extension UIView {

    @objc func blurBackground(style: UIBlurEffect.Style, fallbackColor: UIColor) {
        if !UIAccessibility.isReduceTransparencyEnabled {
            self.backgroundColor = .clear

            let blurEffect = UIBlurEffect(style: style)
            let blurEffectView = UIVisualEffectView(effect: blurEffect)
            //always fill the view
            blurEffectView.frame = self.self.bounds
            blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

            self.insertSubview(blurEffectView, at: 0)
        } else {
            self.backgroundColor = fallbackColor
        }
    }

}

NOTE: If you want to blur the background of an UILabel without affecting the text, you should create a container UIView, add the UILabel to the container UIView as a subview, set the UILabel's backgroundColor to UIColor.clear, and then call blurBackground(style: UIBlurEffect.Style, fallbackColor: UIColor) on the container UIView. Here's a quick example of this written in Swift 5:

let frame = CGRect(x: 50, y: 200, width: 200, height: 50)
let containerView = UIView(frame: frame)
let label = UILabel(frame: frame)
label.text = "Some Text"
label.backgroundColor = UIColor.clear
containerView.addSubview(label)
containerView.blurBackground(style: .dark, fallbackColor: UIColor.black)
Tyler Wood
  • 126
  • 1
  • 6
5

Accepted answer is correct but there's an important step missing here, in case this view - for which you want blurred background - is presented using

[self presentViewController:vc animated:YES completion:nil]

By default, this will negate the blur as UIKit removes the presenter's view, which you are actually blurring. To avoid that removal, add this line before the previous one

vc.modalPresentationStyle = UIModalPresentationOverFullScreen;

Or use other Over styles.

Aleksandar Vacić
  • 4,433
  • 35
  • 35
3

OBJECTIVE-C

UIVisualEffect *blurEffect;
blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
UIVisualEffectView *visualEffectView;
visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
visualEffectView.frame = self.accessImageView.bounds;
[self.accessImageView addSubview:visualEffectView];

SWIFT 3.0

let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = view.bounds
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(blurEffectView)

from : https://stackoverflow.com/a/24083728/4020910

Community
  • 1
  • 1
BennyTheNerd
  • 3,930
  • 1
  • 21
  • 16
2
func blurBackgroundUsingImage(image: UIImage)
{
    var frame                   = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
    var imageView               = UIImageView(frame: frame)
    imageView.image             = image
    imageView.contentMode       = .ScaleAspectFill
    var blurEffect              = UIBlurEffect(style: .Light)
    var blurEffectView          = UIVisualEffectView(effect: blurEffect)
    blurEffectView.frame        = frame
    var transparentWhiteView    = UIView(frame: frame)
    transparentWhiteView.backgroundColor = UIColor(white: 1.0, alpha: 0.30)
    var viewsArray              = [imageView, blurEffectView, transparentWhiteView]

    for index in 0..<viewsArray.count {
        if let oldView = self.view.viewWithTag(index + 1) {
            var oldView         = self.view.viewWithTag(index + 1)
            // Must explicitly unwrap oldView to access its removeFromSuperview() method as of Xcode 6 Beta 5
            oldView!.removeFromSuperview()
        }
        var viewToInsert        = viewsArray[index]
        self.view.insertSubview(viewToInsert, atIndex: index + 1)
        viewToInsert.tag        = index + 1
    }
}
Nagarjun
  • 6,557
  • 5
  • 33
  • 51
Durul Dalkanat
  • 7,266
  • 4
  • 35
  • 36
2

Using UIImageEffects

For people who wants more control, you could make use of Apple's UIImageEffects sample code.

You can copy the code for UIImageEffects from Apple's Developer Library : Blurring and Tinting an Image

And here's how to apply it :

#import "UIImageEffects.h"
...

self.originalImageView.image = [UIImageEffects imageByApplyingLightEffectToImage:[UIImage imageNamed:@"yourImage.png"]];
Community
  • 1
  • 1
Zack Braksa
  • 1,628
  • 18
  • 26
1

Found this by accident, gives me really great (near duplicate with Apple's) results and uses the Acceleration framework. -- http://pastebin.com/6cs6hsyQ *Not written by me

Jake
  • 3,973
  • 24
  • 36
  • 8
    It's actually Apple code from WWDC 2013 with wrong copyright. – Shmidt Dec 17 '13 at 19:29
  • aren't the codes from WWDC copyrighted, and access is only allowed to members with paid subscriptions? – SAFAD Apr 26 '14 at 13:42
  • 1
    Possibly, but the code above I found using Google. I haven't changed the Copyright and I assumed (and still assume) that it has the correct copyright claim. If Apple disagrees, they should put their effort into taking it down. I don't see the relevance. – Jake May 01 '14 at 15:13
1

This answer is based on Mitja Semolic's excellent earlier answer. I've converted it to swift 3, added an explanation to what's happening in coments, made it an extension of a UIViewController so any VC can call it at will, added an unblurred view to show selective application, and added a completion block so that the calling view controller can do whatever it wants at the completion of the blur.

    import UIKit
//This extension implements a blur to the entire screen, puts up a HUD and then waits and dismisses the view.
    extension UIViewController {
        func blurAndShowHUD(duration: Double, message: String, completion: @escaping () -> Void) { //with completion block
            //1. Create the blur effect & the view it will occupy
            let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.light)
            let blurEffectView = UIVisualEffectView()//(effect: blurEffect)
            blurEffectView.frame = self.view.bounds
            blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

        //2. Add the effect view to the main view
            self.view.addSubview(blurEffectView)
        //3. Create the hud and add it to the main view
        let hud = HudView.getHUD(view: self.view, withMessage: message)
        self.view.addSubview(hud)
        //4. Begin applying the blur effect to the effect view
        UIView.animate(withDuration: 0.01, animations: {
            blurEffectView.effect = blurEffect
        })
        //5. Halt the blur effects application to achieve the desired blur radius
        self.view.pauseAnimationsInThisView(delay: 0.004)
        //6. Remove the view (& the HUD) after the completion of the duration
        DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
            blurEffectView.removeFromSuperview()
            hud.removeFromSuperview()
            self.view.resumeAnimationsInThisView()
            completion()
        }
    }
}

extension UIView {
    public func pauseAnimationsInThisView(delay: Double) {
        let time = delay + CFAbsoluteTimeGetCurrent()
        let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, time, 0, 0, 0, { timer in
            let layer = self.layer
            let pausedTime = layer.convertTime(CACurrentMediaTime(), from: nil)
            layer.speed = 0.0
            layer.timeOffset = pausedTime
        })
        CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, CFRunLoopMode.commonModes)
    }
    public func resumeAnimationsInThisView() {
        let pausedTime  = layer.timeOffset

        layer.speed = 1.0
        layer.timeOffset = 0.0
        layer.beginTime = layer.convertTime(CACurrentMediaTime(), from: nil) - pausedTime
    }
}

I've confirmed that it works with both iOS 10.3.1 and iOS 11

James Jordan Taylor
  • 1,560
  • 3
  • 24
  • 38
1

An important supplement to @Joey's answer

This applies to a situation where you want to present a blurred-background UIViewController with UINavigationController.

// suppose you've done blur effect with your presented view controller
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController];

// this is very important, if you don't do this, the blur effect will darken after view did appeared
// the reason is that you actually present navigation controller, not presented controller
// please note it's "OverFullScreen", not "OverCurrentContext"
nav.modalPresentationStyle = UIModalPresentationOverFullScreen;

UIViewController *presentedViewController = [[UIViewController alloc] init]; 
// the presented view controller's modalPresentationStyle is "OverCurrentContext"
presentedViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;

[presentingViewController presentViewController:nav animated:YES completion:nil];

Enjoy!

steveluoxin
  • 419
  • 4
  • 14
1

Swift 3 Version of Kev's answer to return blurred image -

func blurBgImage(image: UIImage) -> UIImage? {
        let radius: CGFloat = 20;
        let context = CIContext(options: nil);
        let inputImage = CIImage(cgImage: image.cgImage!);
        let filter = CIFilter(name: "CIGaussianBlur");
        filter?.setValue(inputImage, forKey: kCIInputImageKey);
        filter?.setValue("\(radius)", forKey:kCIInputRadiusKey);

        if let result = filter?.value(forKey: kCIOutputImageKey) as? CIImage{

            let rect = CGRect(origin: CGPoint(x: radius * 2,y :radius * 2), size: CGSize(width: image.size.width - radius * 4, height: image.size.height - radius * 4))

            if let cgImage = context.createCGImage(result, from: rect){
                return UIImage(cgImage: cgImage);
                }
        }
        return nil;
    }
Pramod
  • 1,123
  • 2
  • 12
  • 33
1

2019 code

Here's a fuller example using the amazing @AdamBardon technique.

@IBDesignable class ButtonOrSomethingWithBlur: UIButton {

    var ba: UIViewPropertyAnimator?
    private lazy var blurry: BlurryBall = { return BlurryBall() }()

    override func didMoveToSuperview() {
        super.didMoveToSuperview()
        
        // Setup the blurry ball.  BE SURE TO TEARDOWN.
        // Use superb trick to access the internal guassian level of Apple's
        // standard gpu blurrer per stackoverflow.com/a/55378168/294884
        
        superview?.insertSubview(blurry, belowSubview: self)
        ba = UIViewPropertyAnimator(duration:1, curve:.linear) {[weak self] in
            // note, those duration/curve values are simply unusued
            self?.blurry.effect = UIBlurEffect(style: .extraLight)
        }
        ba?.fractionComplete = live.largeplaybutton_blurfactor
    }
    
    override func willMove(toSuperview newSuperview: UIView?) {
        
        // Teardown for the blurry ball - critical
        
        if newSuperview == nil { print("safe teardown")
            ba?.stopAnimation(true)
            ba?.finishAnimation(at: .current)
        }
    }

    override func layoutSubviews() { super.layoutSubviews()
        blurry.frame = bounds, your drawing frame or whatever
    }

{Aside: as a general iOS engineering matter, didMoveToWindow may be more suitable to you than didMoveToSuperview. Secondly, you may use some other way to do the teardown, but the teardown is the two lines of code shown there.}

BlurryBall is just a UIVisualEffectView. Notice the inits for a visual effects view. If you happen to need rounded corners or whatever, do it in this class.

class BlurryBall: UIVisualEffectView {
    
    override init(effect: UIVisualEffect?) { super.init(effect: effect)
        commonInit() }
    
    required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder)
        commonInit() }
    
    private func commonInit() {
        clipsToBounds = true
        backgroundColor = .clear
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        layer.cornerRadius = bounds.width / 2
    }
}
Community
  • 1
  • 1
Fattie
  • 27,874
  • 70
  • 431
  • 719
0

Apple has provided an extension for the UIImage class called UIImage+ImageEffects.h. In this class you have the desired methods for blurring your view

Preet
  • 9
  • 2
0

Here is the Swift 2.0 code for the solution that has been provided in accepted answer:

    //only apply the blur if the user hasn't disabled transparency effects
    if !UIAccessibilityIsReduceTransparencyEnabled() {
        self.view.backgroundColor = UIColor.clearColor()

        let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.Dark)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)
        //always fill the view
        blurEffectView.frame = self.view.bounds
        blurEffectView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]

        self.view.addSubview(blurEffectView) //if you have more UIViews, use an insertSubview API to place it where needed
    } else {
        self.view.backgroundColor = UIColor.blackColor()
    }
RaptoX
  • 2,565
  • 2
  • 14
  • 15
0

You can directly make your Background Blur using "Visual Effect View with Blur" and "Visual Effect View with Blur and Vibrancy".

All you have to do for making Blur Background in iOS Application is...

  1. Go and search for "Visual Effect View with Blur" in Object Library

Step 1 Image

  1. Drag the "Visual Effect View with Blur" in your Storyboard and setup it...

Step 2 Image

  1. Finally... You make your App Background Blur!

Application Layout before clicking on any Button!

Application View After Clicking on Button which makes the whole application background Blur!

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
-1

If adds a dark blur view for tableView, this will beautifully make it:

tableView.backgroundColor = .clear
let blurEffect = UIBlurEffect(style: .dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = tableView.bounds
blurEffectView.autoresizingMask = [.flexibleHeight, .flexibleWidth]


// Assigning blurEffectView to backgroundView instead of addSubview to tableView makes tableView cell not blocked by blurEffectView 
tableView.backgroundView = blurEffectView
Ciao
  • 56
  • 5
-2

Swift 4:

To add an overlay, or the popup view You can also use the Container View with which you get a free View Controller ( you get the Container View from the usual object palette/library)

Steps:

Have a View (ViewForContainer in the pic) that holds this Container View, to dim it when the contents of Container View are displayed. Connect the outlet inside the first View Controller

Hide this View when 1st VC loads

Unhide when Button is clicked enter image description here

To dim this View when the Container View content is displayed, set the Views Background to Black and opacity to 30%

I have added an answer to the popview view creation in other Stackoverflow question https://stackoverflow.com/a/49729431/5438240

ymutlu
  • 6,585
  • 4
  • 35
  • 47
Naishta
  • 11,885
  • 4
  • 72
  • 54
-3

Simple answer is Add a subview and change it's alpha.

UIView *mainView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
UIView *subView = [[UIView alloc] initWithFrame:popupView.frame];
UIColor * backImgColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"blue_Img.png"]];
subView.backgroundColor = backImgColor;
subView.alpha = 0.5;
[mainView addSubview:subView];
Developer
  • 99
  • 1
  • 4