Skip to content

Commit

Permalink
FIX: blur not always being applied, iOS 8 screenshot issues
Browse files Browse the repository at this point in the history
  • Loading branch information
u10int committed Jan 11, 2015
1 parent ce20309 commit aa09d3e
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 135 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,17 @@
2B07457D1826C6020092FA56 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B07457C1826C6020092FA56 /* main.m */; };
2B0745811826C6020092FA56 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B0745801826C6020092FA56 /* AppDelegate.m */; };
2B0745831826C6020092FA56 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2B0745821826C6020092FA56 /* Images.xcassets */; };
2B07458A1826C6020092FA56 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2B0745891826C6020092FA56 /* XCTest.framework */; };
2B07458B1826C6020092FA56 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2B0745701826C6020092FA56 /* Foundation.framework */; };
2B07458C1826C6020092FA56 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2B0745741826C6020092FA56 /* UIKit.framework */; };
2B0745A41826CBAB0092FA56 /* DemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B0745A31826CBAB0092FA56 /* DemoViewController.m */; };
2B0745A71826D0E00092FA56 /* seattle01.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 2B0745A61826D0E00092FA56 /* seattle01.jpg */; };
2B0745AA182729AF0092FA56 /* URBMediaFocusViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B0745A9182729AF0092FA56 /* URBMediaFocusViewController.m */; };
2B18684B183C758500539B97 /* raceforfood.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 2B18684A183C758500539B97 /* raceforfood.jpg */; };
2B18684D183C852900539B97 /* panorama.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 2B18684C183C852900539B97 /* panorama.jpg */; };
2B18684F183C869300539B97 /* panorama_vert.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 2B18684E183C869300539B97 /* panorama_vert.jpg */; };
2B407B1018FCE6DC00D1608E /* animated_thumb.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 2B407B0F18FCE6DB00D1608E /* animated_thumb.jpg */; };
2B7013ED1A3FBA80009A0D6E /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2B7013EC1A3FBA80009A0D6E /* CoreImage.framework */; };
2B82035018E65C8900610831 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2B82034F18E65C8900610831 /* AssetsLibrary.framework */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
2B07458D1826C6020092FA56 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 2B0745651826C6020092FA56 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 2B07456C1826C6020092FA56;
remoteInfo = URBMediaFocusViewControllerDemo;
};
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
2B07456D1826C6020092FA56 /* URBMediaFocusViewControllerDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = URBMediaFocusViewControllerDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
2B0745701826C6020092FA56 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
Expand All @@ -49,7 +37,6 @@
2B07457F1826C6020092FA56 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
2B0745801826C6020092FA56 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
2B0745821826C6020092FA56 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
2B0745881826C6020092FA56 /* URBMediaFocusViewControllerDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = URBMediaFocusViewControllerDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
2B0745891826C6020092FA56 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
2B0745A21826CBAB0092FA56 /* DemoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoViewController.h; sourceTree = "<group>"; };
2B0745A31826CBAB0092FA56 /* DemoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoViewController.m; sourceTree = "<group>"; };
Expand All @@ -60,6 +47,7 @@
2B18684C183C852900539B97 /* panorama.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = panorama.jpg; sourceTree = "<group>"; };
2B18684E183C869300539B97 /* panorama_vert.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = panorama_vert.jpg; sourceTree = "<group>"; };
2B407B0F18FCE6DB00D1608E /* animated_thumb.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = animated_thumb.jpg; sourceTree = "<group>"; };
2B7013EC1A3FBA80009A0D6E /* CoreImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = System/Library/Frameworks/CoreImage.framework; sourceTree = SDKROOT; };
2B82034F18E65C8900610831 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */

Expand All @@ -68,23 +56,14 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
2B7013ED1A3FBA80009A0D6E /* CoreImage.framework in Frameworks */,
2B82035018E65C8900610831 /* AssetsLibrary.framework in Frameworks */,
2B0745731826C6020092FA56 /* CoreGraphics.framework in Frameworks */,
2B0745751826C6020092FA56 /* UIKit.framework in Frameworks */,
2B0745711826C6020092FA56 /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
2B0745851826C6020092FA56 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
2B07458A1826C6020092FA56 /* XCTest.framework in Frameworks */,
2B07458C1826C6020092FA56 /* UIKit.framework in Frameworks */,
2B07458B1826C6020092FA56 /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
Expand All @@ -103,14 +82,14 @@
isa = PBXGroup;
children = (
2B07456D1826C6020092FA56 /* URBMediaFocusViewControllerDemo.app */,
2B0745881826C6020092FA56 /* URBMediaFocusViewControllerDemoTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
2B07456F1826C6020092FA56 /* Frameworks */ = {
isa = PBXGroup;
children = (
2B7013EC1A3FBA80009A0D6E /* CoreImage.framework */,
2B82034F18E65C8900610831 /* AssetsLibrary.framework */,
2B0745701826C6020092FA56 /* Foundation.framework */,
2B0745721826C6020092FA56 /* CoreGraphics.framework */,
Expand Down Expand Up @@ -177,24 +156,6 @@
productReference = 2B07456D1826C6020092FA56 /* URBMediaFocusViewControllerDemo.app */;
productType = "com.apple.product-type.application";
};
2B0745871826C6020092FA56 /* URBMediaFocusViewControllerDemoTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 2B07459C1826C6020092FA56 /* Build configuration list for PBXNativeTarget "URBMediaFocusViewControllerDemoTests" */;
buildPhases = (
2B0745841826C6020092FA56 /* Sources */,
2B0745851826C6020092FA56 /* Frameworks */,
2B0745861826C6020092FA56 /* Resources */,
);
buildRules = (
);
dependencies = (
2B07458E1826C6020092FA56 /* PBXTargetDependency */,
);
name = URBMediaFocusViewControllerDemoTests;
productName = URBMediaFocusViewControllerDemoTests;
productReference = 2B0745881826C6020092FA56 /* URBMediaFocusViewControllerDemoTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
Expand All @@ -207,9 +168,6 @@
2B07456C1826C6020092FA56 = {
DevelopmentTeam = RCNW495Q44;
};
2B0745871826C6020092FA56 = {
TestTargetID = 2B07456C1826C6020092FA56;
};
};
};
buildConfigurationList = 2B0745681826C6020092FA56 /* Build configuration list for PBXProject "URBMediaFocusViewControllerDemo" */;
Expand All @@ -225,7 +183,6 @@
projectRoot = "";
targets = (
2B07456C1826C6020092FA56 /* URBMediaFocusViewControllerDemo */,
2B0745871826C6020092FA56 /* URBMediaFocusViewControllerDemoTests */,
);
};
/* End PBXProject section */
Expand All @@ -245,13 +202,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
2B0745861826C6020092FA56 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
Expand All @@ -266,23 +216,8 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
2B0745841826C6020092FA56 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */

/* Begin PBXTargetDependency section */
2B07458E1826C6020092FA56 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 2B07456C1826C6020092FA56 /* URBMediaFocusViewControllerDemo */;
targetProxy = 2B07458D1826C6020092FA56 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */

/* Begin PBXVariantGroup section */
2B0745791826C6020092FA56 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
Expand Down Expand Up @@ -405,48 +340,6 @@
};
name = Release;
};
2B07459D1826C6020092FA56 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/URBMediaFocusViewControllerDemo.app/URBMediaFocusViewControllerDemo";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "URBMediaFocusViewControllerDemo/URBMediaFocusViewControllerDemo-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = "";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Debug;
};
2B07459E1826C6020092FA56 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/URBMediaFocusViewControllerDemo.app/URBMediaFocusViewControllerDemo";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "URBMediaFocusViewControllerDemo/URBMediaFocusViewControllerDemo-Prefix.pch";
INFOPLIST_FILE = "";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Release;
};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
Expand All @@ -468,15 +361,6 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
2B07459C1826C6020092FA56 /* Build configuration list for PBXNativeTarget "URBMediaFocusViewControllerDemoTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
2B07459D1826C6020092FA56 /* Debug */,
2B07459E1826C6020092FA56 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 2B0745651826C6020092FA56 /* Project object */;
Expand Down
11 changes: 10 additions & 1 deletion SampleProject/URBMediaFocusViewControllerDemo/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,16 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

DemoViewController *controller = [[DemoViewController alloc] initWithNibName:nil bundle:nil];
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:controller];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
self.window.rootViewController = navController;

// uncomment to test component with tab bar navigation
// UIViewController *testController = [[UIViewController alloc] initWithNibName:nil bundle:nil];
// testController.title = @"Test";
// controller.title = @"Demo";
// UITabBarController *tabBarController = [[UITabBarController alloc] initWithNibName:nil bundle:nil];
// tabBarController.viewControllers = @[navController, testController];
// self.window.rootViewController = tabBarController;

self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
Expand Down
70 changes: 56 additions & 14 deletions URBMediaFocusViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

@interface UIView (URBMediaFocusViewController)
- (UIImage *)urb_snapshotImageWithScale:(CGFloat)scale;
- (void)urb_snapshowImageWithScale:(CGFloat)scale completion:(void (^)(UIImage *snapshotImage))completionBlock;
@end

/**
Expand Down Expand Up @@ -65,7 +66,7 @@ @interface URBMediaFocusViewController () <UIScrollViewDelegate, UIActionSheetDe
@property (nonatomic, strong) NSURLConnection *urlConnection;
@property (nonatomic, strong) NSMutableData *urlData;

@property (nonatomic, strong) UIView *blurredSnapshotView;
@property (nonatomic, strong) UIImageView *blurredSnapshotView;
@property (nonatomic, strong) UIView *snapshotView;

@end
Expand All @@ -79,13 +80,15 @@ @implementation URBMediaFocusViewController {
UIInterfaceOrientation _currentOrientation;
BOOL _hasLaidOut;
BOOL _unhideStatusBarOnDismiss;
BOOL _hasGeneratedBlurBackground;
}

- (id)init {
self = [super init];
if (self) {
_hasLaidOut = NO;
_unhideStatusBarOnDismiss = YES;
_hasGeneratedBlurBackground = NO;

self.shouldBlurBackground = YES;
self.parallaxEnabled = YES;
Expand Down Expand Up @@ -240,7 +243,7 @@ - (void)showImage:(UIImage *)image fromRect:(CGRect)fromRect {

// create snapshot of background if parallax is enabled
if (self.parallaxEnabled || self.shouldBlurBackground) {
[self createViewsForBackground];
[self createViewsForBackground:NULL];

// hide status bar, but store whether or not we need to unhide it later when dismissing this view
// NOTE: in iOS 7+, this only works if you set `UIViewControllerBasedStatusBarAppearance` to NO in your Info.plist
Expand Down Expand Up @@ -370,8 +373,7 @@ - (void)showImageFromURL:(NSURL *)url fromRect:(CGRect)fromRect {
}
}

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
self.urlConnection = connection;
[self.loadingView startAnimating];

// stores data as it's loaded from the request
self.urlData = [[NSMutableData alloc] init];
Expand All @@ -385,8 +387,8 @@ - (void)showImageFromURL:(NSURL *)url fromRect:(CGRect)fromRect {
self.loadingView.center = CGPointMake(CGRectGetWidth(self.fromView.frame) / 2.0, CGRectGetHeight(self.fromView.frame) / 2.0);
}

[self.loadingView startAnimating];
[self.urlConnection start];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
self.urlConnection = connection;
}

- (void)dismiss:(BOOL)animated {
Expand Down Expand Up @@ -472,7 +474,7 @@ - (CGRect)convertRect:(CGRect)rect forOrientation:(UIInterfaceOrientation)orient
return rect;
}

- (void)createViewsForBackground {
- (void)createViewsForBackground:(void (^)())completionBlock {
// container view for window
CGRect containerFrame = CGRectMake(0, 0, CGRectGetWidth(self.keyWindow.frame), CGRectGetHeight(self.keyWindow.frame));

Expand Down Expand Up @@ -597,6 +599,7 @@ - (void)hideSnapshotView {

- (void)cleanup {
_hasLaidOut = NO;
_hasGeneratedBlurBackground = NO;
[self.view removeFromSuperview];

if (self.targetViewController) {
Expand Down Expand Up @@ -958,18 +961,57 @@ - (void)reposition {
@implementation UIView (URBMediaFocusViewController)

- (UIImage *)urb_snapshotImageWithScale:(CGFloat)scale {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, scale);
if ([self respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) {
[self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
__strong CALayer *underlyingLayer = self.layer;
CGRect bounds = self.bounds;

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 {
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
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);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, -bounds.origin.x, -bounds.origin.y);

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
[underlyingLayer renderInContext:context];
UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

return image;
return snapshot;
}

- (void)urb_snapshowImageWithScale:(CGFloat)scale completion:(void (^)(UIImage *snapshotImage))completionBlock {
if ([self respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) {
[CATransaction setCompletionBlock:^{
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, scale);
[self drawViewHierarchyInRect:self.bounds afterScreenUpdates:NO];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

if (completionBlock) {
completionBlock(image);
}
}];
}
else {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, scale);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

if (completionBlock) {
completionBlock(image);
}
}
}

@end
Expand Down

0 comments on commit aa09d3e

Please sign in to comment.