From 178d3f1abb928535dbd936b06080244d80a47336 Mon Sep 17 00:00:00 2001 From: zhaoyiqi Date: Fri, 14 Aug 2015 15:32:40 +0800 Subject: [PATCH 01/12] fix snapshotOfUnderlyingView --- FXBlurView/FXBlurView.m | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/FXBlurView/FXBlurView.m b/FXBlurView/FXBlurView.m index 8670ffc..219f654 100755 --- a/FXBlurView/FXBlurView.m +++ b/FXBlurView/FXBlurView.m @@ -510,29 +510,8 @@ - (UIImage *)snapshotOfUnderlyingView CGRect bounds = [blurLayer convertRect:blurLayer.bounds toLayer:underlyingLayer]; self.lastUpdate = [NSDate date]; - CGFloat scale = 0.5; - if (self.iterations) - { - CGFloat blockSize = 12.0f/self.iterations; - scale = blockSize/MAX(blockSize * 2, blurLayer.blurRadius); - scale = 1.0f/floorf(1.0f/scale); - } - CGSize size = bounds.size; - if (self.contentMode == UIViewContentModeScaleToFill || - self.contentMode == UIViewContentModeScaleAspectFill || - self.contentMode == UIViewContentModeScaleAspectFit || - self.contentMode == UIViewContentModeRedraw) - { - //prevents edge artefacts - size.width = floorf(size.width * scale) / scale; - size.height = floorf(size.height * scale) / scale; - } - else if ([[UIDevice currentDevice].systemVersion floatValue] < 7.0f && [UIScreen mainScreen].scale == 1.0f) - { - //prevents pixelation on old devices - scale = 1.0f; - } - UIGraphicsBeginImageContextWithOptions(size, NO, scale); + + UIGraphicsBeginImageContextWithOptions([UIScreen mainScreen].bounds.size, NO, 1); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextTranslateCTM(context, -bounds.origin.x, -bounds.origin.y); From 603ce062e52517d3ee1fe2f67e896b3ee46f4af1 Mon Sep 17 00:00:00 2001 From: zhaoyiqi Date: Mon, 17 Aug 2015 10:49:07 +0800 Subject: [PATCH 02/12] optimized snapshot --- FXBlurView/FXBlurView.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FXBlurView/FXBlurView.m b/FXBlurView/FXBlurView.m index 219f654..0a4ac92 100755 --- a/FXBlurView/FXBlurView.m +++ b/FXBlurView/FXBlurView.m @@ -511,7 +511,7 @@ - (UIImage *)snapshotOfUnderlyingView self.lastUpdate = [NSDate date]; - UIGraphicsBeginImageContextWithOptions([UIScreen mainScreen].bounds.size, NO, 1); + UIGraphicsBeginImageContextWithOptions([UIScreen mainScreen].bounds.size, NO, 1.0/[UIScreen mainScreen].scale); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextTranslateCTM(context, -bounds.origin.x, -bounds.origin.y); From ce8a1dba44611dfd553473b6fb2a40ff29b3f831 Mon Sep 17 00:00:00 2001 From: zhaoyiqi Date: Fri, 11 Sep 2015 16:51:29 +0800 Subject: [PATCH 03/12] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20autoOptim?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FXBlurView/FXBlurView.h | 1 + FXBlurView/FXBlurView.m | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/FXBlurView/FXBlurView.h b/FXBlurView/FXBlurView.h index 598c107..c03697d 100644 --- a/FXBlurView/FXBlurView.h +++ b/FXBlurView/FXBlurView.h @@ -64,6 +64,7 @@ @property (nonatomic, getter = isBlurEnabled) BOOL blurEnabled; @property (nonatomic, getter = isDynamic) BOOL dynamic; +@property (nonatomic, getter = isAutoOptim) BOOL autoOptim; @property (nonatomic, assign) NSUInteger iterations; @property (nonatomic, assign) NSTimeInterval updateInterval; @property (nonatomic, assign) CGFloat blurRadius; diff --git a/FXBlurView/FXBlurView.m b/FXBlurView/FXBlurView.m index 0a4ac92..9202911 100755 --- a/FXBlurView/FXBlurView.m +++ b/FXBlurView/FXBlurView.m @@ -156,6 +156,8 @@ @interface FXBlurView () @property (nonatomic, assign) BOOL blurRadiusSet; @property (nonatomic, assign) BOOL dynamicSet; @property (nonatomic, assign) BOOL blurEnabledSet; +@property (nonatomic, assign) BOOL autoOptimSet; + @property (nonatomic, strong) NSDate *lastUpdate; - (UIImage *)snapshotOfUnderlyingView; @@ -305,6 +307,7 @@ - (void)setUp if (!_iterationsSet) _iterations = 3; if (!_blurRadiusSet) [self blurLayer].blurRadius = 40; if (!_dynamicSet) _dynamic = YES; + if (!_autoOptimSet) _autoOptim = NO; if (!_blurEnabledSet) _blurEnabled = YES; self.updateInterval = _updateInterval; self.layer.magnificationFilter = @"linear"; // kCAFilterLinear @@ -380,6 +383,14 @@ - (void)setBlurEnabled:(BOOL)blurEnabled } } +-(void)setAutoOptim:(BOOL)autoOptim{ + _autoOptimSet=YES; + _autoOptim=autoOptim; + if (_autoOptim) { + [self setNeedsDisplay]; + } +} + - (void)setDynamic:(BOOL)dynamic { _dynamicSet = YES; @@ -511,7 +522,35 @@ - (UIImage *)snapshotOfUnderlyingView self.lastUpdate = [NSDate date]; - UIGraphicsBeginImageContextWithOptions([UIScreen mainScreen].bounds.size, NO, 1.0/[UIScreen mainScreen].scale); + if (_autoOptim) { + CGFloat scale = 0.5; + if (self.iterations) + { + CGFloat blockSize = 12.0f/self.iterations; + scale = blockSize/MAX(blockSize * 2, blurLayer.blurRadius); + scale = 1.0f/floorf(1.0f/scale); + } + CGSize size = bounds.size; + if (self.contentMode == UIViewContentModeScaleToFill || + self.contentMode == UIViewContentModeScaleAspectFill || + self.contentMode == UIViewContentModeScaleAspectFit || + self.contentMode == UIViewContentModeRedraw) + { + //prevents edge artefacts + size.width = floorf(size.width * scale) / scale; + size.height = floorf(size.height * scale) / scale; + } + else if ([[UIDevice currentDevice].systemVersion floatValue] < 7.0f && [UIScreen mainScreen].scale == 1.0f) + { + //prevents pixelation on old devices + scale = 1.0f; + } + UIGraphicsBeginImageContextWithOptions(size, NO, scale); + + } + else{ + UIGraphicsBeginImageContextWithOptions([UIScreen mainScreen].bounds.size, NO, 1.0/[UIScreen mainScreen].scale); + } CGContextRef context = UIGraphicsGetCurrentContext(); CGContextTranslateCTM(context, -bounds.origin.x, -bounds.origin.y); From 34096ebb4d55dd9704361da6edd3bf1d8584dcc8 Mon Sep 17 00:00:00 2001 From: zhaoyiqi Date: Thu, 29 Oct 2015 16:33:20 +0800 Subject: [PATCH 04/12] fix bug --- FXBlurView/FXBlurView.h | 5 +- FXBlurView/FXBlurView.m | 164 ++++++++++++++++++++++++++++++---------- 2 files changed, 130 insertions(+), 39 deletions(-) mode change 100644 => 100755 FXBlurView/FXBlurView.h diff --git a/FXBlurView/FXBlurView.h b/FXBlurView/FXBlurView.h old mode 100644 new mode 100755 index c03697d..2e59f81 --- a/FXBlurView/FXBlurView.h +++ b/FXBlurView/FXBlurView.h @@ -1,7 +1,7 @@ // // FXBlurView.h // -// Version 1.6.3 +// Version 1.6.4 // // Created by Nick Lockwood on 25/08/2013. // Copyright (c) 2013 Charcoal Design @@ -65,6 +65,7 @@ @property (nonatomic, getter = isBlurEnabled) BOOL blurEnabled; @property (nonatomic, getter = isDynamic) BOOL dynamic; @property (nonatomic, getter = isAutoOptim) BOOL autoOptim; + @property (nonatomic, assign) NSUInteger iterations; @property (nonatomic, assign) NSTimeInterval updateInterval; @property (nonatomic, assign) CGFloat blurRadius; @@ -73,6 +74,8 @@ - (void)updateAsynchronously:(BOOL)async completion:(void (^)())completion; +- (void)clearImage; + @end diff --git a/FXBlurView/FXBlurView.m b/FXBlurView/FXBlurView.m index 9202911..6574dbf 100755 --- a/FXBlurView/FXBlurView.m +++ b/FXBlurView/FXBlurView.m @@ -1,7 +1,7 @@ // // FXBlurView.m // -// Version 1.6.3 +// Version 1.6.4 // // Created by Nick Lockwood on 25/08/2013. // Copyright (c) 2013 Charcoal Design @@ -52,13 +52,25 @@ - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)itera { //image must be nonzero size if (floorf(self.size.width) * floorf(self.size.height) <= 0.0f) return self; - + //boxsize must be an odd integer uint32_t boxSize = (uint32_t)(radius * self.scale); if (boxSize % 2 == 0) boxSize ++; - + //create image buffers CGImageRef imageRef = self.CGImage; + + //convert to ARGB if it isn't + if (CGImageGetBitsPerPixel(imageRef) != 32 || + CGImageGetBitsPerComponent(imageRef) != 8 || + !((CGImageGetBitmapInfo(imageRef) & kCGBitmapAlphaInfoMask))) + { + UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale); + [self drawAtPoint:CGPointZero]; + imageRef = UIGraphicsGetImageFromCurrentImageContext().CGImage; + UIGraphicsEndImageContext(); + } + vImage_Buffer buffer1, buffer2; buffer1.width = buffer2.width = CGImageGetWidth(imageRef); buffer1.height = buffer2.height = CGImageGetHeight(imageRef); @@ -66,36 +78,36 @@ - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)itera size_t bytes = buffer1.rowBytes * buffer1.height; buffer1.data = malloc(bytes); buffer2.data = malloc(bytes); - + //create temp buffer void *tempBuffer = malloc((size_t)vImageBoxConvolve_ARGB8888(&buffer1, &buffer2, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend + kvImageGetTempBufferSize)); - + //copy image data CFDataRef dataSource = CGDataProviderCopyData(CGImageGetDataProvider(imageRef)); memcpy(buffer1.data, CFDataGetBytePtr(dataSource), bytes); CFRelease(dataSource); - + for (NSUInteger i = 0; i < iterations; i++) { //perform blur vImageBoxConvolve_ARGB8888(&buffer1, &buffer2, tempBuffer, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend); - + //swap buffers void *temp = buffer1.data; buffer1.data = buffer2.data; buffer2.data = temp; } - + //free buffers free(buffer2.data); free(tempBuffer); - + //create image context from buffer CGContextRef ctx = CGBitmapContextCreate(buffer1.data, buffer1.width, buffer1.height, 8, buffer1.rowBytes, CGImageGetColorSpace(imageRef), CGImageGetBitmapInfo(imageRef)); - + //apply tint if (tintColor && CGColorGetAlpha(tintColor.CGColor) > 0.0f) { @@ -103,7 +115,7 @@ - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)itera CGContextSetBlendMode(ctx, kCGBlendModePlusLighter); CGContextFillRect(ctx, CGRectMake(0, 0, buffer1.width, buffer1.height)); } - + //create image from context imageRef = CGBitmapContextCreateImage(ctx); UIImage *image = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation]; @@ -159,6 +171,7 @@ @interface FXBlurView () @property (nonatomic, assign) BOOL autoOptimSet; @property (nonatomic, strong) NSDate *lastUpdate; +@property (nonatomic, assign) BOOL needsDrawViewHierarchy; - (UIImage *)snapshotOfUnderlyingView; - (BOOL)shouldUpdate; @@ -240,7 +253,7 @@ - (void)updateAsynchronously if (self.blurEnabled && !self.updating && self.updatesEnabled > 0 && [self.views count]) { NSTimeInterval timeUntilNextUpdate = 1.0 / 60; - + //loop through until we find a view that's ready to be drawn self.viewIndex = self.viewIndex % [self.views count]; for (NSUInteger i = self.viewIndex; i < [self.views count]; i++) @@ -253,7 +266,7 @@ - (void)updateAsynchronously { self.updating = YES; [view updateAsynchronously:YES completion:^{ - + //render next view self.updating = NO; self.viewIndex = i + 1; @@ -282,6 +295,8 @@ - (void)updateAsynchronously @implementation FXBlurView +@synthesize underlyingView = _underlyingView; + + (void)setBlurEnabled:(BOOL)blurEnabled { [FXBlurScheduler sharedInstance].blurEnabled = blurEnabled; @@ -307,11 +322,12 @@ - (void)setUp if (!_iterationsSet) _iterations = 3; if (!_blurRadiusSet) [self blurLayer].blurRadius = 40; if (!_dynamicSet) _dynamic = YES; - if (!_autoOptimSet) _autoOptim = NO; if (!_blurEnabledSet) _blurEnabled = YES; + if (!_autoOptimSet) _autoOptim = NO; + self.updateInterval = _updateInterval; self.layer.magnificationFilter = @"linear"; // kCAFilterLinear - + unsigned int numberOfMethods; Method *methods = class_copyMethodList([UIView class], &numberOfMethods); for (unsigned int i = 0; i < numberOfMethods; i++) @@ -325,6 +341,7 @@ - (void)setUp } } free(methods); + } - (id)initWithFrame:(CGRect)frame @@ -351,6 +368,35 @@ - (void)dealloc [[NSNotificationCenter defaultCenter] removeObserver:self]; } + +- (BOOL)viewOrSubviewNeedsDrawViewHierarchy:(UIView *)view +{ + if ([view isKindOfClass:NSClassFromString(@"SKView")] || + [view.layer isKindOfClass:NSClassFromString(@"CAEAGLLayer")] || + [view.layer isKindOfClass:NSClassFromString(@"AVPlayerLayer")] || + ABS(view.layer.transform.m34) > 0) + { + return YES; + } + for (UIView *subview in view.subviews) + { + if ([self viewOrSubviewNeedsDrawViewHierarchy:subview]) + { + return YES; + } + } + return NO; +} + +- (void)willMoveToSuperview:(UIView *)newSuperview +{ + [super willMoveToSuperview:newSuperview]; + if (!_underlyingView) + { + _needsDrawViewHierarchy = [self viewOrSubviewNeedsDrawViewHierarchy:newSuperview]; + } +} + - (void)setIterations:(NSUInteger)iterations { _iterationsSet = YES; @@ -410,6 +456,13 @@ - (UIView *)underlyingView return _underlyingView ?: self.superview; } +- (void)setUnderlyingView:(UIView *)underlyingView +{ + _underlyingView = underlyingView; + _needsDrawViewHierarchy = [self viewOrSubviewNeedsDrawViewHierarchy:self.underlyingView]; + [self setNeedsDisplay]; +} + - (CALayer *)underlyingLayer { return self.underlyingView.layer; @@ -438,6 +491,11 @@ - (void)setTintColor:(UIColor *)tintColor [self setNeedsDisplay]; } +- (void)clearImage { + self.layer.contents = nil; + [self setNeedsDisplay]; +} + - (void)didMoveToSuperview { [super didMoveToSuperview]; @@ -471,7 +529,7 @@ - (void)setNeedsDisplay - (BOOL)shouldUpdate { __strong CALayer *underlyingLayer = [self underlyingLayer]; - + return underlyingLayer && !underlyingLayer.hidden && self.blurEnabled && [FXBlurScheduler sharedInstance].blurEnabled && @@ -493,7 +551,7 @@ - (void)displayLayer:(__unused CALayer *)layer { CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:key]; animation.fromValue = [layer.presentationLayer valueForKey:key]; - + //CAMediatiming attributes animation.beginTime = action.beginTime; animation.duration = action.duration; @@ -503,11 +561,11 @@ - (void)displayLayer:(__unused CALayer *)layer animation.repeatDuration = action.repeatDuration; animation.autoreverses = action.autoreverses; animation.fillMode = action.fillMode; - + //CAAnimation attributes animation.timingFunction = action.timingFunction; animation.delegate = action.delegate; - + return animation; } } @@ -519,16 +577,15 @@ - (UIImage *)snapshotOfUnderlyingView __strong FXBlurLayer *blurLayer = [self blurPresentationLayer]; __strong CALayer *underlyingLayer = [self underlyingLayer]; CGRect bounds = [blurLayer convertRect:blurLayer.bounds toLayer:underlyingLayer]; - - self.lastUpdate = [NSDate date]; + self.lastUpdate = [NSDate date]; if (_autoOptim) { CGFloat scale = 0.5; if (self.iterations) { - CGFloat blockSize = 12.0f/self.iterations; + CGFloat blockSize = 12.0/self.iterations; scale = blockSize/MAX(blockSize * 2, blurLayer.blurRadius); - scale = 1.0f/floorf(1.0f/scale); + scale = 1.0/floor(1.0/scale); } CGSize size = bounds.size; if (self.contentMode == UIViewContentModeScaleToFill || @@ -537,29 +594,56 @@ - (UIImage *)snapshotOfUnderlyingView self.contentMode == UIViewContentModeRedraw) { //prevents edge artefacts - size.width = floorf(size.width * scale) / scale; - size.height = floorf(size.height * scale) / scale; + size.width = floor(size.width * scale) / scale; + size.height = floor(size.height * scale) / scale; } - else if ([[UIDevice currentDevice].systemVersion floatValue] < 7.0f && [UIScreen mainScreen].scale == 1.0f) + else if ([[UIDevice currentDevice].systemVersion floatValue] < 7.0 && [UIScreen mainScreen].scale == 1.0) { //prevents pixelation on old devices - scale = 1.0f; + scale = 1.0; } UIGraphicsBeginImageContextWithOptions(size, NO, scale); - } else{ UIGraphicsBeginImageContextWithOptions([UIScreen mainScreen].bounds.size, NO, 1.0/[UIScreen mainScreen].scale); } - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextTranslateCTM(context, -bounds.origin.x, -bounds.origin.y); - NSArray *hiddenViews = [self prepareUnderlyingViewForSnapshot]; - [underlyingLayer renderInContext:context]; - [self restoreSuperviewAfterSnapshot:hiddenViews]; - UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return snapshot; + CGContextRef context = UIGraphicsGetCurrentContext(); + if (context) + { + CGContextTranslateCTM(context, -bounds.origin.x, -bounds.origin.y); + + NSArray *hiddenViews = [self prepareUnderlyingViewForSnapshot]; + if (self.needsDrawViewHierarchy) + { + __strong UIView *underlyingView = self.underlyingView; + [underlyingView drawViewHierarchyInRect:underlyingView.bounds afterScreenUpdates:YES]; + } + else + { + [underlyingLayer renderInContext:context]; + } + [self restoreSuperviewAfterSnapshot:hiddenViews]; + UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return snapshot; + } + return nil; +} + +- (NSArray *)hideEmptyLayers:(CALayer *)layer +{ + NSMutableArray *layers = [NSMutableArray array]; + if (CGRectIsEmpty(layer.bounds)) + { + layer.hidden = YES; + [layers addObject:layer]; + } + for (CALayer *sublayer in layer.sublayers) + { + [layers addObjectsFromArray:[self hideEmptyLayers:sublayer]]; + } + return layers; } - (NSArray *)prepareUnderlyingViewForSnapshot @@ -584,6 +668,10 @@ - (NSArray *)prepareUnderlyingViewForSnapshot } } } + + //also hide any sublayers with empty bounds to prevent a crash on iOS 8 + [layers addObjectsFromArray:[self hideEmptyLayers:underlyingLayer]]; + return layers; } @@ -616,10 +704,10 @@ - (void)updateAsynchronously:(BOOL)async completion:(void (^)())completion if (async) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - + UIImage *blurredImage = [self blurredSnapshot:snapshot radius:self.blurRadius]; dispatch_sync(dispatch_get_main_queue(), ^{ - + [self setLayerContents:blurredImage]; if (completion) completion(); }); From bfeaa4e4b64da543a9b87995c8e530e292b72249 Mon Sep 17 00:00:00 2001 From: zhaoyiqi Date: Tue, 2 Feb 2016 19:02:05 +0800 Subject: [PATCH 05/12] fix bug --- FXBlurView/FXBlurView.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FXBlurView/FXBlurView.m b/FXBlurView/FXBlurView.m index 6574dbf..17b50be 100755 --- a/FXBlurView/FXBlurView.m +++ b/FXBlurView/FXBlurView.m @@ -533,7 +533,7 @@ - (BOOL)shouldUpdate return underlyingLayer && !underlyingLayer.hidden && self.blurEnabled && [FXBlurScheduler sharedInstance].blurEnabled && - !CGRectIsEmpty([self.layer.presentationLayer ?: self.layer bounds]) && !CGRectIsEmpty(underlyingLayer.bounds); + !CGRectIsEmpty([(CALayer*)self.layer.presentationLayer ?: self.layer bounds]) && !CGRectIsEmpty(underlyingLayer.bounds); } - (void)displayLayer:(__unused CALayer *)layer From c2a1e695f35f38df0b89bb9e3dad9c7cc3f9f16b Mon Sep 17 00:00:00 2001 From: MinYoung Kim Date: Thu, 4 Dec 2014 03:28:37 +0900 Subject: [PATCH 06/12] fix console error on iOS8 issue https://github.com/nicklockwood/FXBlurView/issues/44. # Conflicts: # FXBlurView/FXBlurView.m --- FXBlurView/FXBlurView.m | 206 ++++++++++------------------------------ 1 file changed, 50 insertions(+), 156 deletions(-) diff --git a/FXBlurView/FXBlurView.m b/FXBlurView/FXBlurView.m index 17b50be..17441e1 100755 --- a/FXBlurView/FXBlurView.m +++ b/FXBlurView/FXBlurView.m @@ -1,7 +1,7 @@ // // FXBlurView.m // -// Version 1.6.4 +// Version 1.6.3 // // Created by Nick Lockwood on 25/08/2013. // Copyright (c) 2013 Charcoal Design @@ -52,25 +52,13 @@ - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)itera { //image must be nonzero size if (floorf(self.size.width) * floorf(self.size.height) <= 0.0f) return self; - + //boxsize must be an odd integer uint32_t boxSize = (uint32_t)(radius * self.scale); if (boxSize % 2 == 0) boxSize ++; - + //create image buffers CGImageRef imageRef = self.CGImage; - - //convert to ARGB if it isn't - if (CGImageGetBitsPerPixel(imageRef) != 32 || - CGImageGetBitsPerComponent(imageRef) != 8 || - !((CGImageGetBitmapInfo(imageRef) & kCGBitmapAlphaInfoMask))) - { - UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale); - [self drawAtPoint:CGPointZero]; - imageRef = UIGraphicsGetImageFromCurrentImageContext().CGImage; - UIGraphicsEndImageContext(); - } - vImage_Buffer buffer1, buffer2; buffer1.width = buffer2.width = CGImageGetWidth(imageRef); buffer1.height = buffer2.height = CGImageGetHeight(imageRef); @@ -78,36 +66,36 @@ - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)itera size_t bytes = buffer1.rowBytes * buffer1.height; buffer1.data = malloc(bytes); buffer2.data = malloc(bytes); - + //create temp buffer void *tempBuffer = malloc((size_t)vImageBoxConvolve_ARGB8888(&buffer1, &buffer2, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend + kvImageGetTempBufferSize)); - + //copy image data CFDataRef dataSource = CGDataProviderCopyData(CGImageGetDataProvider(imageRef)); memcpy(buffer1.data, CFDataGetBytePtr(dataSource), bytes); CFRelease(dataSource); - + for (NSUInteger i = 0; i < iterations; i++) { //perform blur vImageBoxConvolve_ARGB8888(&buffer1, &buffer2, tempBuffer, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend); - + //swap buffers void *temp = buffer1.data; buffer1.data = buffer2.data; buffer2.data = temp; } - + //free buffers free(buffer2.data); free(tempBuffer); - + //create image context from buffer CGContextRef ctx = CGBitmapContextCreate(buffer1.data, buffer1.width, buffer1.height, 8, buffer1.rowBytes, CGImageGetColorSpace(imageRef), - CGImageGetBitmapInfo(imageRef)); - + (CGBitmapInfo)kCGImageAlphaNoneSkipLast); + //apply tint if (tintColor && CGColorGetAlpha(tintColor.CGColor) > 0.0f) { @@ -115,7 +103,7 @@ - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)itera CGContextSetBlendMode(ctx, kCGBlendModePlusLighter); CGContextFillRect(ctx, CGRectMake(0, 0, buffer1.width, buffer1.height)); } - + //create image from context imageRef = CGBitmapContextCreateImage(ctx); UIImage *image = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation]; @@ -168,10 +156,7 @@ @interface FXBlurView () @property (nonatomic, assign) BOOL blurRadiusSet; @property (nonatomic, assign) BOOL dynamicSet; @property (nonatomic, assign) BOOL blurEnabledSet; -@property (nonatomic, assign) BOOL autoOptimSet; - @property (nonatomic, strong) NSDate *lastUpdate; -@property (nonatomic, assign) BOOL needsDrawViewHierarchy; - (UIImage *)snapshotOfUnderlyingView; - (BOOL)shouldUpdate; @@ -253,7 +238,7 @@ - (void)updateAsynchronously if (self.blurEnabled && !self.updating && self.updatesEnabled > 0 && [self.views count]) { NSTimeInterval timeUntilNextUpdate = 1.0 / 60; - + //loop through until we find a view that's ready to be drawn self.viewIndex = self.viewIndex % [self.views count]; for (NSUInteger i = self.viewIndex; i < [self.views count]; i++) @@ -266,7 +251,7 @@ - (void)updateAsynchronously { self.updating = YES; [view updateAsynchronously:YES completion:^{ - + //render next view self.updating = NO; self.viewIndex = i + 1; @@ -295,8 +280,6 @@ - (void)updateAsynchronously @implementation FXBlurView -@synthesize underlyingView = _underlyingView; - + (void)setBlurEnabled:(BOOL)blurEnabled { [FXBlurScheduler sharedInstance].blurEnabled = blurEnabled; @@ -323,11 +306,9 @@ - (void)setUp if (!_blurRadiusSet) [self blurLayer].blurRadius = 40; if (!_dynamicSet) _dynamic = YES; if (!_blurEnabledSet) _blurEnabled = YES; - if (!_autoOptimSet) _autoOptim = NO; - self.updateInterval = _updateInterval; self.layer.magnificationFilter = @"linear"; // kCAFilterLinear - + unsigned int numberOfMethods; Method *methods = class_copyMethodList([UIView class], &numberOfMethods); for (unsigned int i = 0; i < numberOfMethods; i++) @@ -341,7 +322,6 @@ - (void)setUp } } free(methods); - } - (id)initWithFrame:(CGRect)frame @@ -368,35 +348,6 @@ - (void)dealloc [[NSNotificationCenter defaultCenter] removeObserver:self]; } - -- (BOOL)viewOrSubviewNeedsDrawViewHierarchy:(UIView *)view -{ - if ([view isKindOfClass:NSClassFromString(@"SKView")] || - [view.layer isKindOfClass:NSClassFromString(@"CAEAGLLayer")] || - [view.layer isKindOfClass:NSClassFromString(@"AVPlayerLayer")] || - ABS(view.layer.transform.m34) > 0) - { - return YES; - } - for (UIView *subview in view.subviews) - { - if ([self viewOrSubviewNeedsDrawViewHierarchy:subview]) - { - return YES; - } - } - return NO; -} - -- (void)willMoveToSuperview:(UIView *)newSuperview -{ - [super willMoveToSuperview:newSuperview]; - if (!_underlyingView) - { - _needsDrawViewHierarchy = [self viewOrSubviewNeedsDrawViewHierarchy:newSuperview]; - } -} - - (void)setIterations:(NSUInteger)iterations { _iterationsSet = YES; @@ -429,14 +380,6 @@ - (void)setBlurEnabled:(BOOL)blurEnabled } } --(void)setAutoOptim:(BOOL)autoOptim{ - _autoOptimSet=YES; - _autoOptim=autoOptim; - if (_autoOptim) { - [self setNeedsDisplay]; - } -} - - (void)setDynamic:(BOOL)dynamic { _dynamicSet = YES; @@ -456,13 +399,6 @@ - (UIView *)underlyingView return _underlyingView ?: self.superview; } -- (void)setUnderlyingView:(UIView *)underlyingView -{ - _underlyingView = underlyingView; - _needsDrawViewHierarchy = [self viewOrSubviewNeedsDrawViewHierarchy:self.underlyingView]; - [self setNeedsDisplay]; -} - - (CALayer *)underlyingLayer { return self.underlyingView.layer; @@ -491,11 +427,6 @@ - (void)setTintColor:(UIColor *)tintColor [self setNeedsDisplay]; } -- (void)clearImage { - self.layer.contents = nil; - [self setNeedsDisplay]; -} - - (void)didMoveToSuperview { [super didMoveToSuperview]; @@ -529,11 +460,11 @@ - (void)setNeedsDisplay - (BOOL)shouldUpdate { __strong CALayer *underlyingLayer = [self underlyingLayer]; - + return underlyingLayer && !underlyingLayer.hidden && self.blurEnabled && [FXBlurScheduler sharedInstance].blurEnabled && - !CGRectIsEmpty([(CALayer*)self.layer.presentationLayer ?: self.layer bounds]) && !CGRectIsEmpty(underlyingLayer.bounds); + !CGRectIsEmpty([self.layer.presentationLayer ?: self.layer bounds]) && !CGRectIsEmpty(underlyingLayer.bounds); } - (void)displayLayer:(__unused CALayer *)layer @@ -551,7 +482,7 @@ - (void)displayLayer:(__unused CALayer *)layer { CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:key]; animation.fromValue = [layer.presentationLayer valueForKey:key]; - + //CAMediatiming attributes animation.beginTime = action.beginTime; animation.duration = action.duration; @@ -561,11 +492,11 @@ - (void)displayLayer:(__unused CALayer *)layer animation.repeatDuration = action.repeatDuration; animation.autoreverses = action.autoreverses; animation.fillMode = action.fillMode; - + //CAAnimation attributes animation.timingFunction = action.timingFunction; animation.delegate = action.delegate; - + return animation; } } @@ -577,73 +508,40 @@ - (UIImage *)snapshotOfUnderlyingView __strong FXBlurLayer *blurLayer = [self blurPresentationLayer]; __strong CALayer *underlyingLayer = [self underlyingLayer]; CGRect bounds = [blurLayer convertRect:blurLayer.bounds toLayer:underlyingLayer]; - - self.lastUpdate = [NSDate date]; - if (_autoOptim) { - CGFloat scale = 0.5; - if (self.iterations) - { - CGFloat blockSize = 12.0/self.iterations; - scale = blockSize/MAX(blockSize * 2, blurLayer.blurRadius); - scale = 1.0/floor(1.0/scale); - } - CGSize size = bounds.size; - if (self.contentMode == UIViewContentModeScaleToFill || - self.contentMode == UIViewContentModeScaleAspectFill || - self.contentMode == UIViewContentModeScaleAspectFit || - self.contentMode == UIViewContentModeRedraw) - { - //prevents edge artefacts - size.width = floor(size.width * scale) / scale; - size.height = floor(size.height * scale) / scale; - } - else if ([[UIDevice currentDevice].systemVersion floatValue] < 7.0 && [UIScreen mainScreen].scale == 1.0) - { - //prevents pixelation on old devices - scale = 1.0; - } - UIGraphicsBeginImageContextWithOptions(size, NO, scale); - } - else{ - UIGraphicsBeginImageContextWithOptions([UIScreen mainScreen].bounds.size, NO, 1.0/[UIScreen mainScreen].scale); - } - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context) + self.lastUpdate = [NSDate date]; + CGFloat scale = 0.5; + if (self.iterations) { - CGContextTranslateCTM(context, -bounds.origin.x, -bounds.origin.y); - - NSArray *hiddenViews = [self prepareUnderlyingViewForSnapshot]; - if (self.needsDrawViewHierarchy) - { - __strong UIView *underlyingView = self.underlyingView; - [underlyingView drawViewHierarchyInRect:underlyingView.bounds afterScreenUpdates:YES]; - } - else - { - [underlyingLayer renderInContext:context]; - } - [self restoreSuperviewAfterSnapshot:hiddenViews]; - UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return snapshot; - } - return nil; -} - -- (NSArray *)hideEmptyLayers:(CALayer *)layer -{ - NSMutableArray *layers = [NSMutableArray array]; - if (CGRectIsEmpty(layer.bounds)) + CGFloat blockSize = 12.0f/self.iterations; + scale = blockSize/MAX(blockSize * 2, blurLayer.blurRadius); + scale = 1.0f/floorf(1.0f/scale); + } + CGSize size = bounds.size; + if (self.contentMode == UIViewContentModeScaleToFill || + self.contentMode == UIViewContentModeScaleAspectFill || + self.contentMode == UIViewContentModeScaleAspectFit || + self.contentMode == UIViewContentModeRedraw) { - layer.hidden = YES; - [layers addObject:layer]; + //prevents edge artefacts + size.width = floorf(size.width * scale) / scale; + size.height = floorf(size.height * scale) / scale; } - for (CALayer *sublayer in layer.sublayers) + else if ([[UIDevice currentDevice].systemVersion floatValue] < 7.0f && [UIScreen mainScreen].scale == 1.0f) { - [layers addObjectsFromArray:[self hideEmptyLayers:sublayer]]; + //prevents pixelation on old devices + scale = 1.0f; } - return layers; + UIGraphicsBeginImageContextWithOptions(size, NO, scale); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextTranslateCTM(context, -bounds.origin.x, -bounds.origin.y); + + NSArray *hiddenViews = [self prepareUnderlyingViewForSnapshot]; + [underlyingLayer renderInContext:context]; + [self restoreSuperviewAfterSnapshot:hiddenViews]; + UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return snapshot; } - (NSArray *)prepareUnderlyingViewForSnapshot @@ -668,10 +566,6 @@ - (NSArray *)prepareUnderlyingViewForSnapshot } } } - - //also hide any sublayers with empty bounds to prevent a crash on iOS 8 - [layers addObjectsFromArray:[self hideEmptyLayers:underlyingLayer]]; - return layers; } @@ -704,10 +598,10 @@ - (void)updateAsynchronously:(BOOL)async completion:(void (^)())completion if (async) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - + UIImage *blurredImage = [self blurredSnapshot:snapshot radius:self.blurRadius]; dispatch_sync(dispatch_get_main_queue(), ^{ - + [self setLayerContents:blurredImage]; if (completion) completion(); }); From 9d56a094d8cc3b91123466100f0cb2d100a072b5 Mon Sep 17 00:00:00 2001 From: Dustin Bachrach Date: Mon, 8 Dec 2014 15:40:49 -0800 Subject: [PATCH 07/12] blurredImageWithRadius:iterations:tintColor: assumes image is in ARGB format Courtesy: @gresrun --- FXBlurView/FXBlurView.m | 61 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/FXBlurView/FXBlurView.m b/FXBlurView/FXBlurView.m index 17441e1..462ac9b 100755 --- a/FXBlurView/FXBlurView.m +++ b/FXBlurView/FXBlurView.m @@ -59,6 +59,19 @@ - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)itera //create image buffers CGImageRef imageRef = self.CGImage; + + if (![self isARGB8888:imageRef]) { + // Convert to ARGB if it isn't + CGContextRef ctx = [self createARGBBitmapContextFromImage:imageRef]; + CGRect rect = {{0, 0}, {CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)}}; + // Draw the image to the bitmap context. Once we draw, the memory + // allocated for the context for rendering will then contain the + // raw image data in the desired color space and byte order + CGContextDrawImage(ctx, rect, imageRef); + imageRef = CGBitmapContextCreateImage(ctx); + CGContextRelease(ctx); + } + vImage_Buffer buffer1, buffer2; buffer1.width = buffer2.width = CGImageGetWidth(imageRef); buffer1.height = buffer2.height = CGImageGetHeight(imageRef); @@ -113,6 +126,54 @@ - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)itera return image; } +- (BOOL)isARGB8888:(CGImageRef)imageRef { + return (CGImageGetBitsPerPixel(imageRef) == 32 + && CGImageGetBitsPerComponent(imageRef) == 8 + && (CGImageGetBitmapInfo(imageRef) & kCGBitmapAlphaInfoMask)); +} + +- (CGContextRef)createARGBBitmapContextFromImage:(CGImageRef)inImage { + // Get image width, height. We'll use the entire image. + size_t pixelsWide = CGImageGetWidth(inImage); + size_t pixelsHigh = CGImageGetHeight(inImage); + // Declare the number of bytes per row. Each pixel in the bitmap in this + // example is represented by 4 bytes; 8 bits each of red, green, blue, and alpha. + int bitmapBytesPerRow = (pixelsWide * 4); + int bitmapByteCount = (bitmapBytesPerRow * pixelsHigh); + // Use the generic RGB color space. + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + if (colorSpace == NULL) { + NSLog(@"Error allocating color space"); + return NULL; + } + // Allocate memory for image data. This is the destination in memory + // where any drawing to the bitmap context will be rendered. + void *bitmapData = malloc(bitmapByteCount); + if (bitmapData == NULL) { + NSLog(@"Memory not allocated!"); + CGColorSpaceRelease(colorSpace); + return NULL; + } + // Create the bitmap context. We want pre-multiplied ARGB, 8-bits + // per component. Regardless of what the source image format is + // (CMYK, Grayscale, and so on) it will be converted over to the format + // specified here by CGBitmapContextCreate. + CGContextRef context = CGBitmapContextCreate(bitmapData, + pixelsWide, + pixelsHigh, + 8, // bits per component + bitmapBytesPerRow, + colorSpace, + (CGBitmapInfo) kCGImageAlphaPremultipliedFirst); + if (context == NULL) { + free(bitmapData); + NSLog(@"Context not created!"); + } + // Make sure and release colorspace before returning + CGColorSpaceRelease(colorSpace); + return context; +} + @end From dac52a0e748565d74a420d5bb867384b949f833a Mon Sep 17 00:00:00 2001 From: YosonHao Date: Wed, 24 Dec 2014 11:00:01 +0800 Subject: [PATCH 08/12] fix error ": CGContextRestoreGState: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update." --- FXBlurView/FXBlurView.m | 1 + 1 file changed, 1 insertion(+) diff --git a/FXBlurView/FXBlurView.m b/FXBlurView/FXBlurView.m index 462ac9b..df38f51 100755 --- a/FXBlurView/FXBlurView.m +++ b/FXBlurView/FXBlurView.m @@ -118,6 +118,7 @@ - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)itera } //create image from context + UIGraphicsPushContext(ctx); imageRef = CGBitmapContextCreateImage(ctx); UIImage *image = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation]; CGImageRelease(imageRef); From 72ff36eca0499cd49f7b4d0ae5da836f2d0fbb28 Mon Sep 17 00:00:00 2001 From: Rich Hong Date: Wed, 4 Feb 2015 11:26:00 -0500 Subject: [PATCH 09/12] Hide empty sublayers to prevent renderInContext crash on iOS 8 --- FXBlurView/FXBlurView.m | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/FXBlurView/FXBlurView.m b/FXBlurView/FXBlurView.m index df38f51..117abb0 100755 --- a/FXBlurView/FXBlurView.m +++ b/FXBlurView/FXBlurView.m @@ -606,6 +606,19 @@ - (UIImage *)snapshotOfUnderlyingView return snapshot; } +- (NSArray *)hideEmptyLayers:(CALayer *)layer +{ + NSMutableArray *layers = [NSMutableArray array]; + if (CGRectIsEmpty(layer.bounds)) { + layer.hidden = YES; + [layers addObject:layer]; + } + for (CALayer *sublayer in layer.sublayers) { + [layers addObjectsFromArray:[self hideEmptyLayers:sublayer]]; + } + return layers; +} + - (NSArray *)prepareUnderlyingViewForSnapshot { __strong CALayer *blurlayer = [self blurLayer]; @@ -628,6 +641,10 @@ - (NSArray *)prepareUnderlyingViewForSnapshot } } } + + // Also hide any sublayers with empty bounds to prevent a crash on iOS 8 + [layers addObjectsFromArray:[self hideEmptyLayers:underlyingLayer]]; + return layers; } From 7ae30f415f57e09da7fa6292784ea7031197208d Mon Sep 17 00:00:00 2001 From: zhaoyiqi Date: Tue, 15 Mar 2016 20:46:03 +0800 Subject: [PATCH 10/12] Merge remote-tracking branch 'nicklockwood/master' into HEAD # Conflicts: # FXBlurView/FXBlurView.m # Conflicts: # FXBlurView/FXBlurView.m --- .travis.yml | 7 + .../OverlayExample.xcodeproj/project.pbxproj | 2 + FXBlurView.podspec.json | 4 +- FXBlurView/FXBlurView.m | 261 +++++---- LICENCE.md | 2 +- README.md | 12 +- .../project.pbxproj | 2 + .../project.pbxproj | 2 + .../FXBlurView.xcodeproj/project.pbxproj | 505 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcschemes/FXBlurView.xcscheme | 83 +++ .../FXBlurViewTests-Info.plist | 22 + .../FXBlurViewTests/FXBlurViewTests.m | 17 + .../en.lproj/InfoPlist.strings | 2 + .../project.pbxproj | 10 +- .../FXBlurViewExample-Prefix.pch | 14 - 16 files changed, 812 insertions(+), 140 deletions(-) create mode 100644 .travis.yml create mode 100644 Tests/FXBlurView/FXBlurView.xcodeproj/project.pbxproj create mode 100644 Tests/FXBlurView/FXBlurView.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Tests/FXBlurView/FXBlurView.xcodeproj/xcshareddata/xcschemes/FXBlurView.xcscheme create mode 100644 Tests/FXBlurView/FXBlurViewTests/FXBlurViewTests-Info.plist create mode 100644 Tests/FXBlurView/FXBlurViewTests/FXBlurViewTests.m create mode 100644 Tests/FXBlurView/FXBlurViewTests/en.lproj/InfoPlist.strings delete mode 100644 Tests/MultiViewTest/FXBlurViewExample/FXBlurViewExample-Prefix.pch diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..37f2911 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +language: objective-c +xcode_project: Tests/FXBlurView/FXBlurView.xcodeproj +xcode_scheme: FXBlurView +xcode_sdk: iphonesimulator7.0 +before_script: + - brew update + - brew upgrade xctool diff --git a/Examples/OverlayExample/OverlayExample.xcodeproj/project.pbxproj b/Examples/OverlayExample/OverlayExample.xcodeproj/project.pbxproj index 375d07e..1168abf 100644 --- a/Examples/OverlayExample/OverlayExample.xcodeproj/project.pbxproj +++ b/Examples/OverlayExample/OverlayExample.xcodeproj/project.pbxproj @@ -74,7 +74,9 @@ 012FDEDB17D13C23003F0236 /* Frameworks */, 012FDEDA17D13C23003F0236 /* Products */, ); + indentWidth = 4; sourceTree = ""; + tabWidth = 4; }; 012FDEDA17D13C23003F0236 /* Products */ = { isa = PBXGroup; diff --git a/FXBlurView.podspec.json b/FXBlurView.podspec.json index fd0378e..21992d0 100644 --- a/FXBlurView.podspec.json +++ b/FXBlurView.podspec.json @@ -1,6 +1,6 @@ { "name": "FXBlurView", - "version": "1.6.3", + "version": "1.6.4", "license": "zlib", "summary": "UIView subclass that replicates the iOS 7 realtime background blur effect, but works on iOS 5 and above.", "authors": { @@ -8,7 +8,7 @@ }, "source": { "git": "https://github.com/nicklockwood/FXBlurView.git", - "tag": "1.6.3" + "tag": "1.6.4" }, "homepage": "http://github.com/nicklockwood/FXBlurView", "platforms": { diff --git a/FXBlurView/FXBlurView.m b/FXBlurView/FXBlurView.m index 117abb0..c697c4e 100755 --- a/FXBlurView/FXBlurView.m +++ b/FXBlurView/FXBlurView.m @@ -1,7 +1,7 @@ // // FXBlurView.m // -// Version 1.6.3 +// Version 1.6.4 // // Created by Nick Lockwood on 25/08/2013. // Copyright (c) 2013 Charcoal Design @@ -52,26 +52,25 @@ - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)itera { //image must be nonzero size if (floorf(self.size.width) * floorf(self.size.height) <= 0.0f) return self; - + //boxsize must be an odd integer uint32_t boxSize = (uint32_t)(radius * self.scale); if (boxSize % 2 == 0) boxSize ++; - + //create image buffers CGImageRef imageRef = self.CGImage; - - if (![self isARGB8888:imageRef]) { - // Convert to ARGB if it isn't - CGContextRef ctx = [self createARGBBitmapContextFromImage:imageRef]; - CGRect rect = {{0, 0}, {CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)}}; - // Draw the image to the bitmap context. Once we draw, the memory - // allocated for the context for rendering will then contain the - // raw image data in the desired color space and byte order - CGContextDrawImage(ctx, rect, imageRef); - imageRef = CGBitmapContextCreateImage(ctx); - CGContextRelease(ctx); - } - + + //convert to ARGB if it isn't + if (CGImageGetBitsPerPixel(imageRef) != 32 || + CGImageGetBitsPerComponent(imageRef) != 8 || + !((CGImageGetBitmapInfo(imageRef) & kCGBitmapAlphaInfoMask))) + { + UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale); + [self drawAtPoint:CGPointZero]; + imageRef = UIGraphicsGetImageFromCurrentImageContext().CGImage; + UIGraphicsEndImageContext(); + } + vImage_Buffer buffer1, buffer2; buffer1.width = buffer2.width = CGImageGetWidth(imageRef); buffer1.height = buffer2.height = CGImageGetHeight(imageRef); @@ -79,36 +78,36 @@ - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)itera size_t bytes = buffer1.rowBytes * buffer1.height; buffer1.data = malloc(bytes); buffer2.data = malloc(bytes); - + //create temp buffer void *tempBuffer = malloc((size_t)vImageBoxConvolve_ARGB8888(&buffer1, &buffer2, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend + kvImageGetTempBufferSize)); - + //copy image data CFDataRef dataSource = CGDataProviderCopyData(CGImageGetDataProvider(imageRef)); memcpy(buffer1.data, CFDataGetBytePtr(dataSource), bytes); CFRelease(dataSource); - + for (NSUInteger i = 0; i < iterations; i++) { //perform blur vImageBoxConvolve_ARGB8888(&buffer1, &buffer2, tempBuffer, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend); - + //swap buffers void *temp = buffer1.data; buffer1.data = buffer2.data; buffer2.data = temp; } - + //free buffers free(buffer2.data); free(tempBuffer); - + //create image context from buffer CGContextRef ctx = CGBitmapContextCreate(buffer1.data, buffer1.width, buffer1.height, 8, buffer1.rowBytes, CGImageGetColorSpace(imageRef), - (CGBitmapInfo)kCGImageAlphaNoneSkipLast); - + CGImageGetBitmapInfo(imageRef)); + //apply tint if (tintColor && CGColorGetAlpha(tintColor.CGColor) > 0.0f) { @@ -116,9 +115,8 @@ - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)itera CGContextSetBlendMode(ctx, kCGBlendModePlusLighter); CGContextFillRect(ctx, CGRectMake(0, 0, buffer1.width, buffer1.height)); } - + //create image from context - UIGraphicsPushContext(ctx); imageRef = CGBitmapContextCreateImage(ctx); UIImage *image = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation]; CGImageRelease(imageRef); @@ -127,54 +125,6 @@ - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)itera return image; } -- (BOOL)isARGB8888:(CGImageRef)imageRef { - return (CGImageGetBitsPerPixel(imageRef) == 32 - && CGImageGetBitsPerComponent(imageRef) == 8 - && (CGImageGetBitmapInfo(imageRef) & kCGBitmapAlphaInfoMask)); -} - -- (CGContextRef)createARGBBitmapContextFromImage:(CGImageRef)inImage { - // Get image width, height. We'll use the entire image. - size_t pixelsWide = CGImageGetWidth(inImage); - size_t pixelsHigh = CGImageGetHeight(inImage); - // Declare the number of bytes per row. Each pixel in the bitmap in this - // example is represented by 4 bytes; 8 bits each of red, green, blue, and alpha. - int bitmapBytesPerRow = (pixelsWide * 4); - int bitmapByteCount = (bitmapBytesPerRow * pixelsHigh); - // Use the generic RGB color space. - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - if (colorSpace == NULL) { - NSLog(@"Error allocating color space"); - return NULL; - } - // Allocate memory for image data. This is the destination in memory - // where any drawing to the bitmap context will be rendered. - void *bitmapData = malloc(bitmapByteCount); - if (bitmapData == NULL) { - NSLog(@"Memory not allocated!"); - CGColorSpaceRelease(colorSpace); - return NULL; - } - // Create the bitmap context. We want pre-multiplied ARGB, 8-bits - // per component. Regardless of what the source image format is - // (CMYK, Grayscale, and so on) it will be converted over to the format - // specified here by CGBitmapContextCreate. - CGContextRef context = CGBitmapContextCreate(bitmapData, - pixelsWide, - pixelsHigh, - 8, // bits per component - bitmapBytesPerRow, - colorSpace, - (CGBitmapInfo) kCGImageAlphaPremultipliedFirst); - if (context == NULL) { - free(bitmapData); - NSLog(@"Context not created!"); - } - // Make sure and release colorspace before returning - CGColorSpaceRelease(colorSpace); - return context; -} - @end @@ -218,7 +168,10 @@ @interface FXBlurView () @property (nonatomic, assign) BOOL blurRadiusSet; @property (nonatomic, assign) BOOL dynamicSet; @property (nonatomic, assign) BOOL blurEnabledSet; +@property (nonatomic, assign) BOOL autoOptimSet; + @property (nonatomic, strong) NSDate *lastUpdate; +@property (nonatomic, assign) BOOL needsDrawViewHierarchy; - (UIImage *)snapshotOfUnderlyingView; - (BOOL)shouldUpdate; @@ -300,7 +253,7 @@ - (void)updateAsynchronously if (self.blurEnabled && !self.updating && self.updatesEnabled > 0 && [self.views count]) { NSTimeInterval timeUntilNextUpdate = 1.0 / 60; - + //loop through until we find a view that's ready to be drawn self.viewIndex = self.viewIndex % [self.views count]; for (NSUInteger i = self.viewIndex; i < [self.views count]; i++) @@ -313,7 +266,7 @@ - (void)updateAsynchronously { self.updating = YES; [view updateAsynchronously:YES completion:^{ - + //render next view self.updating = NO; self.viewIndex = i + 1; @@ -342,6 +295,8 @@ - (void)updateAsynchronously @implementation FXBlurView +@synthesize underlyingView = _underlyingView; + + (void)setBlurEnabled:(BOOL)blurEnabled { [FXBlurScheduler sharedInstance].blurEnabled = blurEnabled; @@ -368,9 +323,11 @@ - (void)setUp if (!_blurRadiusSet) [self blurLayer].blurRadius = 40; if (!_dynamicSet) _dynamic = YES; if (!_blurEnabledSet) _blurEnabled = YES; + if (!_autoOptimSet) _autoOptim = NO; + self.updateInterval = _updateInterval; self.layer.magnificationFilter = @"linear"; // kCAFilterLinear - + unsigned int numberOfMethods; Method *methods = class_copyMethodList([UIView class], &numberOfMethods); for (unsigned int i = 0; i < numberOfMethods; i++) @@ -384,6 +341,7 @@ - (void)setUp } } free(methods); + } - (id)initWithFrame:(CGRect)frame @@ -410,6 +368,35 @@ - (void)dealloc [[NSNotificationCenter defaultCenter] removeObserver:self]; } + +- (BOOL)viewOrSubviewNeedsDrawViewHierarchy:(UIView *)view +{ + if ([view isKindOfClass:NSClassFromString(@"SKView")] || + [view.layer isKindOfClass:NSClassFromString(@"CAEAGLLayer")] || + [view.layer isKindOfClass:NSClassFromString(@"AVPlayerLayer")] || + ABS(view.layer.transform.m34) > 0) + { + return YES; + } + for (UIView *subview in view.subviews) + { + if ([self viewOrSubviewNeedsDrawViewHierarchy:subview]) + { + return YES; + } + } + return NO; +} + +- (void)willMoveToSuperview:(UIView *)newSuperview +{ + [super willMoveToSuperview:newSuperview]; + if (!_underlyingView) + { + _needsDrawViewHierarchy = [self viewOrSubviewNeedsDrawViewHierarchy:newSuperview]; + } +} + - (void)setIterations:(NSUInteger)iterations { _iterationsSet = YES; @@ -442,6 +429,14 @@ - (void)setBlurEnabled:(BOOL)blurEnabled } } +-(void)setAutoOptim:(BOOL)autoOptim{ + _autoOptimSet=YES; + _autoOptim=autoOptim; + if (_autoOptim) { + [self setNeedsDisplay]; + } +} + - (void)setDynamic:(BOOL)dynamic { _dynamicSet = YES; @@ -461,6 +456,13 @@ - (UIView *)underlyingView return _underlyingView ?: self.superview; } +- (void)setUnderlyingView:(UIView *)underlyingView +{ + _underlyingView = underlyingView; + _needsDrawViewHierarchy = [self viewOrSubviewNeedsDrawViewHierarchy:self.underlyingView]; + [self setNeedsDisplay]; +} + - (CALayer *)underlyingLayer { return self.underlyingView.layer; @@ -489,6 +491,11 @@ - (void)setTintColor:(UIColor *)tintColor [self setNeedsDisplay]; } +- (void)clearImage { + self.layer.contents = nil; + [self setNeedsDisplay]; +} + - (void)didMoveToSuperview { [super didMoveToSuperview]; @@ -522,11 +529,11 @@ - (void)setNeedsDisplay - (BOOL)shouldUpdate { __strong CALayer *underlyingLayer = [self underlyingLayer]; - + return underlyingLayer && !underlyingLayer.hidden && self.blurEnabled && [FXBlurScheduler sharedInstance].blurEnabled && - !CGRectIsEmpty([self.layer.presentationLayer ?: self.layer bounds]) && !CGRectIsEmpty(underlyingLayer.bounds); + !CGRectIsEmpty([(CALayer*)self.layer.presentationLayer ?: self.layer bounds]) && !CGRectIsEmpty(underlyingLayer.bounds); } - (void)displayLayer:(__unused CALayer *)layer @@ -544,7 +551,7 @@ - (void)displayLayer:(__unused CALayer *)layer { CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:key]; animation.fromValue = [layer.presentationLayer valueForKey:key]; - + //CAMediatiming attributes animation.beginTime = action.beginTime; animation.duration = action.duration; @@ -554,11 +561,11 @@ - (void)displayLayer:(__unused CALayer *)layer animation.repeatDuration = action.repeatDuration; animation.autoreverses = action.autoreverses; animation.fillMode = action.fillMode; - + //CAAnimation attributes animation.timingFunction = action.timingFunction; animation.delegate = action.delegate; - + return animation; } } @@ -570,50 +577,70 @@ - (UIImage *)snapshotOfUnderlyingView __strong FXBlurLayer *blurLayer = [self blurPresentationLayer]; __strong CALayer *underlyingLayer = [self underlyingLayer]; CGRect bounds = [blurLayer convertRect:blurLayer.bounds toLayer:underlyingLayer]; - + self.lastUpdate = [NSDate date]; - CGFloat scale = 0.5; - if (self.iterations) - { - CGFloat blockSize = 12.0f/self.iterations; - scale = blockSize/MAX(blockSize * 2, blurLayer.blurRadius); - scale = 1.0f/floorf(1.0f/scale); - } - CGSize size = bounds.size; - if (self.contentMode == UIViewContentModeScaleToFill || - self.contentMode == UIViewContentModeScaleAspectFill || - self.contentMode == UIViewContentModeScaleAspectFit || - self.contentMode == UIViewContentModeRedraw) - { - //prevents edge artefacts - size.width = floorf(size.width * scale) / scale; - size.height = floorf(size.height * scale) / scale; + if (_autoOptim) { + CGFloat scale = 0.5; + if (self.iterations) + { + CGFloat blockSize = 12.0/self.iterations; + scale = blockSize/MAX(blockSize * 2, blurLayer.blurRadius); + scale = 1.0/floor(1.0/scale); + } + CGSize size = bounds.size; + if (self.contentMode == UIViewContentModeScaleToFill || + self.contentMode == UIViewContentModeScaleAspectFill || + self.contentMode == UIViewContentModeScaleAspectFit || + self.contentMode == UIViewContentModeRedraw) + { + //prevents edge artefacts + size.width = floor(size.width * scale) / scale; + size.height = floor(size.height * scale) / scale; + } + else if ([[UIDevice currentDevice].systemVersion floatValue] < 7.0 && [UIScreen mainScreen].scale == 1.0) + { + //prevents pixelation on old devices + scale = 1.0; + } + UIGraphicsBeginImageContextWithOptions(size, NO, scale); } - else if ([[UIDevice currentDevice].systemVersion floatValue] < 7.0f && [UIScreen mainScreen].scale == 1.0f) - { - //prevents pixelation on old devices - scale = 1.0f; + else{ + UIGraphicsBeginImageContextWithOptions([UIScreen mainScreen].bounds.size, NO, 1.0/[UIScreen mainScreen].scale); } - UIGraphicsBeginImageContextWithOptions(size, NO, scale); CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextTranslateCTM(context, -bounds.origin.x, -bounds.origin.y); - - NSArray *hiddenViews = [self prepareUnderlyingViewForSnapshot]; - [underlyingLayer renderInContext:context]; - [self restoreSuperviewAfterSnapshot:hiddenViews]; - UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return snapshot; + if (context) + { + CGContextTranslateCTM(context, -bounds.origin.x, -bounds.origin.y); + + NSArray *hiddenViews = [self prepareUnderlyingViewForSnapshot]; + if (self.needsDrawViewHierarchy) + { + __strong UIView *underlyingView = self.underlyingView; + [underlyingView drawViewHierarchyInRect:underlyingView.bounds afterScreenUpdates:YES]; + } + else + { + [underlyingLayer renderInContext:context]; + } + [self restoreSuperviewAfterSnapshot:hiddenViews]; + UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return snapshot; + } + + return nil; } - (NSArray *)hideEmptyLayers:(CALayer *)layer { NSMutableArray *layers = [NSMutableArray array]; - if (CGRectIsEmpty(layer.bounds)) { + if (CGRectIsEmpty(layer.bounds)) + { layer.hidden = YES; [layers addObject:layer]; } - for (CALayer *sublayer in layer.sublayers) { + for (CALayer *sublayer in layer.sublayers) + { [layers addObjectsFromArray:[self hideEmptyLayers:sublayer]]; } return layers; @@ -642,7 +669,7 @@ - (NSArray *)prepareUnderlyingViewForSnapshot } } - // Also hide any sublayers with empty bounds to prevent a crash on iOS 8 + //also hide any sublayers with empty bounds to prevent a crash on iOS 8 [layers addObjectsFromArray:[self hideEmptyLayers:underlyingLayer]]; return layers; @@ -677,10 +704,10 @@ - (void)updateAsynchronously:(BOOL)async completion:(void (^)())completion if (async) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - + UIImage *blurredImage = [self blurredSnapshot:snapshot radius:self.blurRadius]; dispatch_sync(dispatch_get_main_queue(), ^{ - + [self setLayerContents:blurredImage]; if (completion) completion(); }); diff --git a/LICENCE.md b/LICENCE.md index f7a7c74..5dd2250 100755 --- a/LICENCE.md +++ b/LICENCE.md @@ -1,6 +1,6 @@ FXBlurView -Version 1.6.3, November 1st, 2014 +Version 1.6.4, September 2nd, 2015 Copyright (C) 2013 Charcoal Design diff --git a/README.md b/README.md index 2279d40..fcd302c 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ FXBlurView is a UIView subclass that replicates the iOS 7 realtime background bl Supported iOS & SDK Versions ----------------------------- -* Supported build target - iOS 8.1 (Xcode 6.1, Apple LLVM compiler 6.0) -* Earliest supported deployment target - iOS 6.0 +* Supported build target - iOS 8.4 (Xcode 6.4, Apple LLVM compiler 6.1) +* Earliest supported deployment target - iOS 7.0 * Earliest compatible deployment target - iOS 4.3 NOTE: 'Supported' means that the library has been tested with this version. 'Compatible' means that the library should work on this iOS version (i.e. it doesn't rely on any unavailable SDK features) but is no longer being tested for compatibility and may require tweaking or bug fixes to run correctly. @@ -114,6 +114,14 @@ FAQ Release Notes ----------------- +Version 1.6.4 + +- `blurredImageWithRadius:iterations:tintColor:` now works if image is not in ARGB format +- Fixed ": CGContextRestoreGState: invalid context 0x0." +- Empty sublayers are now hidden before snapshotting to prevent renderInContext crash on iOS 8 +- FXBlurView now automatically uses slower drawViewHierarchyInRect method when needed to capture content +- Added Travis integration + Version 1.6.3 - FXBlurView image background is no longer opaque/black, so it can be used as a translucent overlay diff --git a/Tests/AnimationTest/FXBlurViewExample.xcodeproj/project.pbxproj b/Tests/AnimationTest/FXBlurViewExample.xcodeproj/project.pbxproj index 58a3781..46c5bd7 100644 --- a/Tests/AnimationTest/FXBlurViewExample.xcodeproj/project.pbxproj +++ b/Tests/AnimationTest/FXBlurViewExample.xcodeproj/project.pbxproj @@ -74,7 +74,9 @@ 01F3119217CA5C4600C54664 /* Frameworks */, 01F3119117CA5C4600C54664 /* Products */, ); + indentWidth = 4; sourceTree = ""; + tabWidth = 4; }; 01F3119117CA5C4600C54664 /* Products */ = { isa = PBXGroup; diff --git a/Tests/EdgeTest/FXBlurViewExample.xcodeproj/project.pbxproj b/Tests/EdgeTest/FXBlurViewExample.xcodeproj/project.pbxproj index fda381a..c3c7ffc 100644 --- a/Tests/EdgeTest/FXBlurViewExample.xcodeproj/project.pbxproj +++ b/Tests/EdgeTest/FXBlurViewExample.xcodeproj/project.pbxproj @@ -275,6 +275,7 @@ 01F311B417CA5C4600C54664 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "FXBlurViewExample/FXBlurViewExample-Prefix.pch"; @@ -292,6 +293,7 @@ 01F311B517CA5C4600C54664 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "FXBlurViewExample/FXBlurViewExample-Prefix.pch"; diff --git a/Tests/FXBlurView/FXBlurView.xcodeproj/project.pbxproj b/Tests/FXBlurView/FXBlurView.xcodeproj/project.pbxproj new file mode 100644 index 0000000..ab7f954 --- /dev/null +++ b/Tests/FXBlurView/FXBlurView.xcodeproj/project.pbxproj @@ -0,0 +1,505 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 2D66632A190F71E4003A9E04 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D666329190F71E4003A9E04 /* Foundation.framework */; }; + 2D66632F190F71E4003A9E04 /* FXBlurView.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2D66632E190F71E4003A9E04 /* FXBlurView.h */; }; + 2D666331190F71E4003A9E04 /* FXBlurView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D666330190F71E4003A9E04 /* FXBlurView.m */; }; + 2D666338190F71E4003A9E04 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D666337190F71E4003A9E04 /* XCTest.framework */; }; + 2D666339190F71E4003A9E04 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D666329190F71E4003A9E04 /* Foundation.framework */; }; + 2D66633E190F71E5003A9E04 /* libFXBlurView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D666326190F71E4003A9E04 /* libFXBlurView.a */; }; + 2D666344190F71E5003A9E04 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2D666342190F71E5003A9E04 /* InfoPlist.strings */; }; + 2D666346190F71E5003A9E04 /* FXBlurViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D666345190F71E5003A9E04 /* FXBlurViewTests.m */; }; + 2D666350190F7429003A9E04 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D66634F190F7429003A9E04 /* UIKit.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 2D66633C190F71E5003A9E04 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2D66631E190F71E4003A9E04 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2D666325190F71E4003A9E04; + remoteInfo = FXBlurView; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 2D666324190F71E4003A9E04 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + 2D66632F190F71E4003A9E04 /* FXBlurView.h in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 2D666326190F71E4003A9E04 /* libFXBlurView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFXBlurView.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 2D666329190F71E4003A9E04 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 2D66632E190F71E4003A9E04 /* FXBlurView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FXBlurView.h; sourceTree = ""; }; + 2D666330190F71E4003A9E04 /* FXBlurView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FXBlurView.m; sourceTree = ""; }; + 2D666336190F71E4003A9E04 /* FXBlurViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FXBlurViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 2D666337190F71E4003A9E04 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + 2D666341190F71E5003A9E04 /* FXBlurViewTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "FXBlurViewTests-Info.plist"; sourceTree = ""; }; + 2D666343190F71E5003A9E04 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 2D666345190F71E5003A9E04 /* FXBlurViewTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FXBlurViewTests.m; sourceTree = ""; }; + 2D66634F190F7429003A9E04 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2D666323190F71E4003A9E04 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2D66632A190F71E4003A9E04 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2D666333190F71E4003A9E04 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2D666350190F7429003A9E04 /* UIKit.framework in Frameworks */, + 2D666338190F71E4003A9E04 /* XCTest.framework in Frameworks */, + 2D666339190F71E4003A9E04 /* Foundation.framework in Frameworks */, + 2D66633E190F71E5003A9E04 /* libFXBlurView.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2D66631D190F71E4003A9E04 = { + isa = PBXGroup; + children = ( + 2D66632B190F71E4003A9E04 /* FXBlurView */, + 2D66633F190F71E5003A9E04 /* FXBlurViewTests */, + 2D666328190F71E4003A9E04 /* Frameworks */, + 2D666327190F71E4003A9E04 /* Products */, + ); + sourceTree = ""; + }; + 2D666327190F71E4003A9E04 /* Products */ = { + isa = PBXGroup; + children = ( + 2D666326190F71E4003A9E04 /* libFXBlurView.a */, + 2D666336190F71E4003A9E04 /* FXBlurViewTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 2D666328190F71E4003A9E04 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 2D66634F190F7429003A9E04 /* UIKit.framework */, + 2D666329190F71E4003A9E04 /* Foundation.framework */, + 2D666337190F71E4003A9E04 /* XCTest.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 2D66632B190F71E4003A9E04 /* FXBlurView */ = { + isa = PBXGroup; + children = ( + 2D66632E190F71E4003A9E04 /* FXBlurView.h */, + 2D666330190F71E4003A9E04 /* FXBlurView.m */, + ); + name = FXBlurView; + path = ../../FXBlurView; + sourceTree = ""; + }; + 2D66633F190F71E5003A9E04 /* FXBlurViewTests */ = { + isa = PBXGroup; + children = ( + 2D666345190F71E5003A9E04 /* FXBlurViewTests.m */, + 2D666340190F71E5003A9E04 /* Supporting Files */, + ); + path = FXBlurViewTests; + sourceTree = ""; + }; + 2D666340190F71E5003A9E04 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 2D666341190F71E5003A9E04 /* FXBlurViewTests-Info.plist */, + 2D666342190F71E5003A9E04 /* InfoPlist.strings */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 2D666325190F71E4003A9E04 /* FXBlurView */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2D666349190F71E5003A9E04 /* Build configuration list for PBXNativeTarget "FXBlurView" */; + buildPhases = ( + 2D666322190F71E4003A9E04 /* Sources */, + 2D666323190F71E4003A9E04 /* Frameworks */, + 2D666324190F71E4003A9E04 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = FXBlurView; + productName = FXBlurView; + productReference = 2D666326190F71E4003A9E04 /* libFXBlurView.a */; + productType = "com.apple.product-type.library.static"; + }; + 2D666335190F71E4003A9E04 /* FXBlurViewTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2D66634C190F71E5003A9E04 /* Build configuration list for PBXNativeTarget "FXBlurViewTests" */; + buildPhases = ( + 2D666332190F71E4003A9E04 /* Sources */, + 2D666333190F71E4003A9E04 /* Frameworks */, + 2D666334190F71E4003A9E04 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 2D66633D190F71E5003A9E04 /* PBXTargetDependency */, + ); + name = FXBlurViewTests; + productName = FXBlurViewTests; + productReference = 2D666336190F71E4003A9E04 /* FXBlurViewTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 2D66631E190F71E4003A9E04 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0510; + ORGANIZATIONNAME = "Charcoal Design"; + }; + buildConfigurationList = 2D666321190F71E4003A9E04 /* Build configuration list for PBXProject "FXBlurView" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 2D66631D190F71E4003A9E04; + productRefGroup = 2D666327190F71E4003A9E04 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 2D666325190F71E4003A9E04 /* FXBlurView */, + 2D666335190F71E4003A9E04 /* FXBlurViewTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 2D666334190F71E4003A9E04 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2D666344190F71E5003A9E04 /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 2D666322190F71E4003A9E04 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2D666331190F71E4003A9E04 /* FXBlurView.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2D666332190F71E4003A9E04 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2D666346190F71E5003A9E04 /* FXBlurViewTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 2D66633D190F71E5003A9E04 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 2D666325190F71E4003A9E04 /* FXBlurView */; + targetProxy = 2D66633C190F71E5003A9E04 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 2D666342190F71E5003A9E04 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 2D666343190F71E5003A9E04 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 2D666347190F71E5003A9E04 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_CXX0X_EXTENSIONS = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; + CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = NO; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MULTIPLE_DEFINITION_TYPES_FOR_SELECTOR = NO; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_PEDANTIC = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_STRICT_SELECTOR_MATCH = NO; + GCC_WARN_UNDECLARED_SELECTOR = NO; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.1; + ONLY_ACTIVE_ARCH = YES; + RUN_CLANG_STATIC_ANALYZER = YES; + SDKROOT = iphoneos; + WARNING_CFLAGS = ( + "-Weverything", + "-Wno-variadic-macros", + "-Wno-gnu-zero-variadic-macro-arguments", + "-Wno-gnu-statement-expression", + "-Wno-objc-missing-property-synthesis", + "-Wno-sign-compare", + "-Wno-auto-import", + ); + }; + name = Debug; + }; + 2D666348190F71E5003A9E04 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_CXX0X_EXTENSIONS = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; + CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = NO; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MULTIPLE_DEFINITION_TYPES_FOR_SELECTOR = NO; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_PEDANTIC = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_STRICT_SELECTOR_MATCH = NO; + GCC_WARN_UNDECLARED_SELECTOR = NO; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.1; + RUN_CLANG_STATIC_ANALYZER = YES; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = ( + "-Weverything", + "-Wno-variadic-macros", + "-Wno-gnu-zero-variadic-macro-arguments", + "-Wno-gnu-statement-expression", + "-Wno-objc-missing-property-synthesis", + "-Wno-sign-compare", + "-Wno-auto-import", + ); + }; + name = Release; + }; + 2D66634A190F71E5003A9E04 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/FXBlurView.dst; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 2D66634B190F71E5003A9E04 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/FXBlurView.dst; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 2D66634D190F71E5003A9E04 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + "$(DEVELOPER_FRAMEWORKS_DIR)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "FXBlurViewTests/FXBlurViewTests-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WARNING_CFLAGS = ( + "-Weverything", + "-Wno-variadic-macros", + "-Wno-gnu-zero-variadic-macro-arguments", + "-Wno-gnu-statement-expression", + "-Wno-objc-missing-property-synthesis", + "-Wno-sign-compare", + "-Wno-auto-import", + "-Wno-documentation-unknown-command", + ); + WRAPPER_EXTENSION = xctest; + }; + name = Debug; + }; + 2D66634E190F71E5003A9E04 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + "$(DEVELOPER_FRAMEWORKS_DIR)", + ); + INFOPLIST_FILE = "FXBlurViewTests/FXBlurViewTests-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WARNING_CFLAGS = ( + "-Weverything", + "-Wno-variadic-macros", + "-Wno-gnu-zero-variadic-macro-arguments", + "-Wno-gnu-statement-expression", + "-Wno-objc-missing-property-synthesis", + "-Wno-sign-compare", + "-Wno-auto-import", + "-Wno-documentation-unknown-command", + ); + WRAPPER_EXTENSION = xctest; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2D666321190F71E4003A9E04 /* Build configuration list for PBXProject "FXBlurView" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2D666347190F71E5003A9E04 /* Debug */, + 2D666348190F71E5003A9E04 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2D666349190F71E5003A9E04 /* Build configuration list for PBXNativeTarget "FXBlurView" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2D66634A190F71E5003A9E04 /* Debug */, + 2D66634B190F71E5003A9E04 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2D66634C190F71E5003A9E04 /* Build configuration list for PBXNativeTarget "FXBlurViewTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2D66634D190F71E5003A9E04 /* Debug */, + 2D66634E190F71E5003A9E04 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 2D66631E190F71E4003A9E04 /* Project object */; +} diff --git a/Tests/FXBlurView/FXBlurView.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Tests/FXBlurView/FXBlurView.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..4c8c628 --- /dev/null +++ b/Tests/FXBlurView/FXBlurView.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Tests/FXBlurView/FXBlurView.xcodeproj/xcshareddata/xcschemes/FXBlurView.xcscheme b/Tests/FXBlurView/FXBlurView.xcodeproj/xcshareddata/xcschemes/FXBlurView.xcscheme new file mode 100644 index 0000000..83de930 --- /dev/null +++ b/Tests/FXBlurView/FXBlurView.xcodeproj/xcshareddata/xcschemes/FXBlurView.xcscheme @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/FXBlurView/FXBlurViewTests/FXBlurViewTests-Info.plist b/Tests/FXBlurView/FXBlurViewTests/FXBlurViewTests-Info.plist new file mode 100644 index 0000000..aada29f --- /dev/null +++ b/Tests/FXBlurView/FXBlurViewTests/FXBlurViewTests-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + uk.co.charcoaldesign.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Tests/FXBlurView/FXBlurViewTests/FXBlurViewTests.m b/Tests/FXBlurView/FXBlurViewTests/FXBlurViewTests.m new file mode 100644 index 0000000..b0ed85f --- /dev/null +++ b/Tests/FXBlurView/FXBlurViewTests/FXBlurViewTests.m @@ -0,0 +1,17 @@ +// +// FXBlurViewTests.m +// FXBlurViewTests +// +// Created by Ashton Williams on 29/04/2014. +// Copyright (c) 2014 Charcoal Design. All rights reserved. +// + +#import + +@interface FXBlurViewTests : XCTestCase + +@end + +@implementation FXBlurViewTests + +@end diff --git a/Tests/FXBlurView/FXBlurViewTests/en.lproj/InfoPlist.strings b/Tests/FXBlurView/FXBlurViewTests/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/Tests/FXBlurView/FXBlurViewTests/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/Tests/MultiViewTest/FXBlurViewExample.xcodeproj/project.pbxproj b/Tests/MultiViewTest/FXBlurViewExample.xcodeproj/project.pbxproj index 1596972..e934526 100644 --- a/Tests/MultiViewTest/FXBlurViewExample.xcodeproj/project.pbxproj +++ b/Tests/MultiViewTest/FXBlurViewExample.xcodeproj/project.pbxproj @@ -31,7 +31,6 @@ 01F3119B17CA5C4600C54664 /* FXBlurViewExample-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "FXBlurViewExample-Info.plist"; sourceTree = ""; }; 01F3119D17CA5C4600C54664 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 01F3119F17CA5C4600C54664 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 01F311A117CA5C4600C54664 /* FXBlurViewExample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FXBlurViewExample-Prefix.pch"; sourceTree = ""; }; 01F311A217CA5C4600C54664 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 01F311A317CA5C4600C54664 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 01F311A517CA5C4600C54664 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; @@ -68,7 +67,9 @@ 01F3119217CA5C4600C54664 /* Frameworks */, 01F3119117CA5C4600C54664 /* Products */, ); + indentWidth = 4; sourceTree = ""; + tabWidth = 4; }; 01F3119117CA5C4600C54664 /* Products */ = { isa = PBXGroup; @@ -106,7 +107,6 @@ 01F3119B17CA5C4600C54664 /* FXBlurViewExample-Info.plist */, 01F3119C17CA5C4600C54664 /* InfoPlist.strings */, 01F3119F17CA5C4600C54664 /* main.m */, - 01F311A117CA5C4600C54664 /* FXBlurViewExample-Prefix.pch */, 01F311A517CA5C4600C54664 /* Default.png */, 01F311A717CA5C4600C54664 /* Default@2x.png */, 01F311A917CA5C4600C54664 /* Default-568h@2x.png */, @@ -228,6 +228,7 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -296,6 +297,7 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -357,7 +359,7 @@ buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "FXBlurViewExample/FXBlurViewExample-Prefix.pch"; + GCC_PREFIX_HEADER = ""; INFOPLIST_FILE = "FXBlurViewExample/FXBlurViewExample-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; @@ -370,7 +372,7 @@ buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "FXBlurViewExample/FXBlurViewExample-Prefix.pch"; + GCC_PREFIX_HEADER = ""; INFOPLIST_FILE = "FXBlurViewExample/FXBlurViewExample-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; diff --git a/Tests/MultiViewTest/FXBlurViewExample/FXBlurViewExample-Prefix.pch b/Tests/MultiViewTest/FXBlurViewExample/FXBlurViewExample-Prefix.pch deleted file mode 100644 index 94a91ce..0000000 --- a/Tests/MultiViewTest/FXBlurViewExample/FXBlurViewExample-Prefix.pch +++ /dev/null @@ -1,14 +0,0 @@ -// -// Prefix header for all source files of the 'FXBlurViewExample' target in the 'FXBlurViewExample' project -// - -#import - -#ifndef __IPHONE_4_0 -#warning "This project uses features only available in iOS SDK 4.0 and later." -#endif - -#ifdef __OBJC__ - #import - #import -#endif From a99615aaf366a95a7bbff24ebb51cc8153dad521 Mon Sep 17 00:00:00 2001 From: zhaoyiqi Date: Tue, 15 Mar 2016 21:20:06 +0800 Subject: [PATCH 11/12] =?UTF-8?q?=E4=BF=AE=E6=AD=A3layer=E9=87=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FXBlurView/FXBlurView.m | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/FXBlurView/FXBlurView.m b/FXBlurView/FXBlurView.m index c697c4e..1421a24 100755 --- a/FXBlurView/FXBlurView.m +++ b/FXBlurView/FXBlurView.m @@ -173,6 +173,9 @@ @interface FXBlurView () @property (nonatomic, strong) NSDate *lastUpdate; @property (nonatomic, assign) BOOL needsDrawViewHierarchy; +@property (nonatomic, strong) NSMutableArray *hiddenArrs; +@property (nonatomic, strong) NSMutableArray *hiddenLayers; + - (UIImage *)snapshotOfUnderlyingView; - (BOOL)shouldUpdate; @@ -366,6 +369,7 @@ - (id)initWithCoder:(NSCoder *)aDecoder - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; + [self revertSuperviewAfterSnapshot:_hiddenLayers]; } @@ -677,9 +681,19 @@ - (NSArray *)prepareUnderlyingViewForSnapshot - (void)restoreSuperviewAfterSnapshot:(NSArray *)hiddenLayers { - for (CALayer *layer in hiddenLayers) - { - layer.hidden = NO; + _hiddenArrs=[[NSMutableArray alloc] init]; + _hiddenLayers=[NSMutableArray arrayWithArray:hiddenLayers]; + for (NSInteger i=0; i Date: Thu, 12 May 2016 16:21:30 +0800 Subject: [PATCH 12/12] =?UTF-8?q?=E6=B7=BB=E5=8A=A0layer=E9=87=8D=E7=BD=AE?= =?UTF-8?q?=E4=B8=8D=E8=BF=98=E5=8E=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FXBlurView/FXBlurView.h | 1 + FXBlurView/FXBlurView.m | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/FXBlurView/FXBlurView.h b/FXBlurView/FXBlurView.h index 2e59f81..ba82ef3 100755 --- a/FXBlurView/FXBlurView.h +++ b/FXBlurView/FXBlurView.h @@ -65,6 +65,7 @@ @property (nonatomic, getter = isBlurEnabled) BOOL blurEnabled; @property (nonatomic, getter = isDynamic) BOOL dynamic; @property (nonatomic, getter = isAutoOptim) BOOL autoOptim; +@property (nonatomic, getter = isRevert) BOOL isRevert; @property (nonatomic, assign) NSUInteger iterations; @property (nonatomic, assign) NSTimeInterval updateInterval; diff --git a/FXBlurView/FXBlurView.m b/FXBlurView/FXBlurView.m index 1421a24..f9c01f9 100755 --- a/FXBlurView/FXBlurView.m +++ b/FXBlurView/FXBlurView.m @@ -169,6 +169,7 @@ @interface FXBlurView () @property (nonatomic, assign) BOOL dynamicSet; @property (nonatomic, assign) BOOL blurEnabledSet; @property (nonatomic, assign) BOOL autoOptimSet; +@property (nonatomic, assign) BOOL isRevertSet; @property (nonatomic, strong) NSDate *lastUpdate; @property (nonatomic, assign) BOOL needsDrawViewHierarchy; @@ -327,6 +328,7 @@ - (void)setUp if (!_dynamicSet) _dynamic = YES; if (!_blurEnabledSet) _blurEnabled = YES; if (!_autoOptimSet) _autoOptim = NO; + if (!_isRevertSet) _isRevert=YES; self.updateInterval = _updateInterval; self.layer.magnificationFilter = @"linear"; // kCAFilterLinear @@ -369,7 +371,9 @@ - (id)initWithCoder:(NSCoder *)aDecoder - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - [self revertSuperviewAfterSnapshot:_hiddenLayers]; + if (_isRevert) { + [self revertSuperviewAfterSnapshot:_hiddenLayers]; + } } @@ -433,6 +437,11 @@ - (void)setBlurEnabled:(BOOL)blurEnabled } } +-(void)setIsRevert:(BOOL)isRevert{ + _isRevertSet=YES; + _isRevert=isRevert; +} + -(void)setAutoOptim:(BOOL)autoOptim{ _autoOptimSet=YES; _autoOptim=autoOptim;