Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix up the app link return to referer view/controller #88

Merged
1 commit merged into from
Apr 2, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 68 additions & 89 deletions Bolts/iOS/BFAppLinkReturnToRefererController.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,12 @@

static const CFTimeInterval kBFViewAnimationDuration = 0.25f;

@interface BFAppLinkReturnToRefererController ()

@property (nonatomic, strong, readwrite) UINavigationController *attachedToNavController; // TODO rename

@end

@implementation BFAppLinkReturnToRefererController {
BFURL *_lastShownBFUrl;
NSURL *_lastShownUrl;
@implementation BFAppLinkReturnToRefererController
{
UINavigationController *_navigationController;
BFAppLinkReturnToRefererView *_view;
}

@synthesize view = _view;

#pragma mark - Object lifecycle

- (instancetype)init {
Expand All @@ -38,41 +31,39 @@ - (instancetype)init {
- (instancetype)initForDisplayAboveNavController:(UINavigationController *)navController {
self = [super init];
if (self) {
_attachedToNavController = navController;

if (_attachedToNavController != nil) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(statusBarFrameWillChange:)
name:UIApplicationWillChangeStatusBarFrameNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(statusBarFrameDidChange:)
name:UIApplicationDidChangeStatusBarFrameNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(orientationDidChange:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
_navigationController = navController;

if (_navigationController != nil) {
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:@selector(statusBarFrameWillChange:)
name:UIApplicationWillChangeStatusBarFrameNotification
object:nil];
[nc addObserver:self
selector:@selector(statusBarFrameDidChange:)
name:UIApplicationDidChangeStatusBarFrameNotification
object:nil];
[nc addObserver:self
selector:@selector(orientationDidChange:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
}
}
return self;
}

- (void)dealloc {
_view.delegate = nil;

if (_attachedToNavController) {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

#pragma mark - Public API

- (BFAppLinkReturnToRefererView *)view {
if (!_view) {
self.view = [[BFAppLinkReturnToRefererView alloc] initWithFrame:CGRectZero];
if (_attachedToNavController) {
[_attachedToNavController.view addSubview:_view];
if (_navigationController) {
[_navigationController.view addSubview:_view];
}
}
return _view;
Expand All @@ -85,21 +76,18 @@ - (void)setView:(BFAppLinkReturnToRefererView *)view {

_view = view;
_view.delegate = self;
if (_attachedToNavController) {

if (_navigationController) {
_view.includeStatusBarInSize = BFIncludeStatusBarInSizeAlways;
}

// TODO
// _view.refererAppLink = _refererAppLink;
}

- (void)showViewForRefererAppLink:(BFAppLink *)refererAppLink {
self.view.refererAppLink = refererAppLink;

[_view sizeToFit];

if (_attachedToNavController) {
if (_navigationController) {
if (!_view.closed) {
dispatch_async(dispatch_get_main_queue(), ^{
[self moveNavigationBar];
Expand All @@ -109,30 +97,27 @@ - (void)showViewForRefererAppLink:(BFAppLink *)refererAppLink {
}

- (void)showViewForRefererURL:(NSURL *)url {
if (![_lastShownUrl isEqual:url]) {
_lastShownUrl = [url copy];
_lastShownBFUrl = [BFURL URLForRenderBackToReferrerBarURL:url];
}
[self showViewForRefererAppLink:_lastShownBFUrl.appLinkReferer];
BFAppLink *appLink = [BFURL URLForRenderBackToReferrerBarURL:url].appLinkReferer;
[self showViewForRefererAppLink:appLink];
}

- (void)removeFromNavController {
if (_attachedToNavController) {
if (_navigationController) {
[_view removeFromSuperview];
_attachedToNavController = nil;
_navigationController = nil;
}
}

#pragma mark - BFAppLinkReturnToRefererViewDelegate

- (void)returnToRefererViewDidTapInsideCloseButton:(BFAppLinkReturnToRefererView *)view {
[self closeViewAnimated:YES];
[self closeViewAnimated:YES explicitlyClosed:YES];
}

- (void)returnToRefererViewDidTapInsideLink:(BFAppLinkReturnToRefererView *)view
link:(BFAppLink *)link {
[self openRefererAppLink:link];
[self closeViewAnimated:NO];
[self closeViewAnimated:NO explicitlyClosed:NO];
}

#pragma mark - Private
Expand All @@ -142,11 +127,11 @@ - (void)statusBarFrameWillChange:(NSNotification *)notification {
CGRect newFrame;
[rectValue getValue:&newFrame];

if (_attachedToNavController && !_view.closed) {
if (newFrame.size.height == 40) {
if (_navigationController && !_view.closed) {
if (CGRectGetHeight(newFrame) == 40) {
UIViewAnimationOptions options = UIViewAnimationOptionBeginFromCurrentState;
[UIView animateWithDuration:kBFViewAnimationDuration delay:0.0 options:options animations:^{
_view.frame = CGRectMake(0.0, 0.0, _view.frame.size.width, 0.0);
_view.frame = CGRectMake(0.0, 0.0, CGRectGetWidth(_view.bounds), 0.0);
} completion:nil];
}
}
Expand All @@ -157,8 +142,8 @@ - (void)statusBarFrameDidChange:(NSNotification *)notification {
CGRect newFrame;
[rectValue getValue:&newFrame];

if (_attachedToNavController && !_view.closed) {
if (newFrame.size.height == 40) {
if (_navigationController && !_view.closed) {
if (CGRectGetHeight(newFrame) == 40) {
UIViewAnimationOptions options = UIViewAnimationOptionBeginFromCurrentState;
[UIView animateWithDuration:kBFViewAnimationDuration delay:0.0 options:options animations:^{
[_view sizeToFit];
Expand All @@ -169,7 +154,7 @@ - (void)statusBarFrameDidChange:(NSNotification *)notification {
}

- (void)orientationDidChange:(NSNotificationCenter *)notification {
if (_attachedToNavController && !_view.closed && _view.frame.size.height > 0) {
if (_navigationController && !_view.closed && CGRectGetHeight(_view.bounds) > 0) {
dispatch_async(dispatch_get_main_queue(), ^{
[self moveNavigationBar];
});
Expand All @@ -178,59 +163,53 @@ - (void)orientationDidChange:(NSNotificationCenter *)notification {

- (void)moveNavigationBar {
if (_view.closed || !_view.refererAppLink) {
return;
return;
}

CGRect oldFrame = _attachedToNavController.navigationBar.frame;

_attachedToNavController.navigationBar.frame = CGRectMake(0,
_view.frame.size.height,
_attachedToNavController.navigationBar.frame.size.width,
_attachedToNavController.navigationBar.frame.size.height);
[self updateNavigationBarY:CGRectGetHeight(_view.bounds)];
}

CGFloat dy = CGRectGetMaxY(_attachedToNavController.navigationBar.frame) - CGRectGetMaxY(oldFrame);
UIView *navigationView = _attachedToNavController.visibleViewController.view.superview;
navigationView.frame = CGRectMake(navigationView.frame.origin.x,
navigationView.frame.origin.y + dy,
navigationView.frame.size.width,
navigationView.frame.size.height - dy);
- (void)updateNavigationBarY:(CGFloat)y
{
UINavigationBar *navigationBar = _navigationController.navigationBar;
CGRect navigationBarFrame = navigationBar.frame;
CGFloat oldContainerViewY = CGRectGetMaxY(navigationBarFrame);
navigationBarFrame.origin.y = y;
navigationBar.frame = navigationBarFrame;

CGFloat dy = CGRectGetMaxY(navigationBarFrame) - oldContainerViewY;
UIView *containerView = _navigationController.visibleViewController.view.superview;
containerView.frame = UIEdgeInsetsInsetRect(containerView.frame, UIEdgeInsetsMake(dy, 0.0, 0.0, 0.0));
}

- (void)closeViewAnimated:(BOOL)animated {
[self closeViewAnimated:animated explicitlyClosed:YES];
}

- (void)closeViewAnimated:(BOOL)animated explicitlyClosed:(BOOL)explicitlyClosed {
void (^closer)(void) = ^{
if (_attachedToNavController) {
CGRect oldFrame = _attachedToNavController.navigationBar.frame;

_attachedToNavController.navigationBar.frame = CGRectMake(0,
_view.statusBarHeight,
_attachedToNavController.navigationBar.frame.size.width,
_attachedToNavController.navigationBar.frame.size.height);

CGFloat dy = CGRectGetMaxY(_attachedToNavController.navigationBar.frame) - CGRectGetMaxY(oldFrame);
UIView *navigationView = _attachedToNavController.visibleViewController.view.superview;
navigationView.frame = CGRectMake(navigationView.frame.origin.x,
navigationView.frame.origin.y + dy,
navigationView.frame.size.width,
navigationView.frame.size.height - dy);
if (_navigationController) {
[self updateNavigationBarY:_view.statusBarHeight];
}

_view.frame = CGRectMake(_view.frame.origin.x,
_view.frame.origin.y,
_view.frame.size.width,
0);
CGRect frame = _view.frame;
frame.size.height = 0.0;
_view.frame = frame;
};

if (animated) {
UIViewAnimationOptions options = UIViewAnimationOptionBeginFromCurrentState;
[UIView animateWithDuration:kBFViewAnimationDuration delay:0.0 options:options animations:^{
[UIView animateWithDuration:kBFViewAnimationDuration animations:^{
closer();
} completion:^(BOOL animateOutFinished) {
_view.closed = YES;
} completion:^(BOOL finished) {
if (explicitlyClosed) {
_view.closed = YES;
}
}];
} else {
closer();
_view.closed = YES;
if (explicitlyClosed) {
_view.closed = YES;
}
}
}

Expand Down
27 changes: 7 additions & 20 deletions Bolts/iOS/BFAppLinkReturnToRefererView.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
@class BFAppLinkReturnToRefererView;
@class BFURL;

typedef enum BFIncludeStatusBarInSize {
BFIncludeStatusBarInSizeNever,
BFIncludeStatusBarInSizeIOS7AndLater,
BFIncludeStatusBarInSizeAlways,
} BFIncludeStatusBarInSize;
typedef NS_ENUM(NSUInteger, BFIncludeStatusBarInSize)
{
BFIncludeStatusBarInSizeNever,
BFIncludeStatusBarInSizeIOS7AndLater,
BFIncludeStatusBarInSizeAlways,
};

/*!
Protocol that a class can implement in order to be notified when the user has navigated back
Expand Down Expand Up @@ -65,7 +66,7 @@ typedef enum BFIncludeStatusBarInSize {
/*!
Indicates whether to extend the size of the view to include the current status bar
size, for use in scenarios where the view might extend under the status bar on iOS 7 and
above; this property has no effect on earlier versions of iOS.
above; this property has no effect on earlier versions of iOS.
*/
@property (nonatomic, assign) BFIncludeStatusBarInSize includeStatusBarInSize;

Expand All @@ -74,18 +75,4 @@ typedef enum BFIncludeStatusBarInSize {
*/
@property (nonatomic, assign) BOOL closed;

/*!
For apps that use a navigation controller, this method allows for displaying the view as
a banner above the navigation bar of the navigation controller. It will listen for orientation
change and other events to ensure it stays properly positioned above the nevigation bar.
If this method is called from, e.g., viewDidAppear, its counterpart, detachFromMainWindow should
be called from, e.g., viewWillDisappear.
*/
//- (void)attachToMainWindowAboveNavigationController:(UINavigationController *)navigationController view:(UIView *)view;

/*!
Indicates that the view should no longer position itself above a navigation bar.
*/
//- (void)detachFromMainWindow;

@end
Loading