diff --git a/TLYShyNavBarSwiftDemo/TLYShyNavBar/Categories/NSObject+TLYSwizzlingHelpers.h b/TLYShyNavBarSwiftDemo/TLYShyNavBar/Categories/NSObject+TLYSwizzlingHelpers.h deleted file mode 100644 index 2394e82..0000000 --- a/TLYShyNavBarSwiftDemo/TLYShyNavBar/Categories/NSObject+TLYSwizzlingHelpers.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// NSObject+TLYSwizzlingHelpers.h -// TLYShyNavBarDemo -// -// Created by Mazyad Alabduljaleel on 6/23/14. -// Copyright (c) 2014 Telly, Inc. All rights reserved. -// - -#import - -@interface NSObject (TLYSwizzlingHelpers) - -+ (void)tly_swizzleClassMethod:(SEL)originalSelector withReplacement:(SEL)replacementSelector; -+ (void)tly_swizzleInstanceMethod:(SEL)originalSelector withReplacement:(SEL)replacementSelector; - -@end diff --git a/TLYShyNavBarSwiftDemo/TLYShyNavBar/Categories/NSObject+TLYSwizzlingHelpers.m b/TLYShyNavBarSwiftDemo/TLYShyNavBar/Categories/NSObject+TLYSwizzlingHelpers.m deleted file mode 100644 index d72f537..0000000 --- a/TLYShyNavBarSwiftDemo/TLYShyNavBar/Categories/NSObject+TLYSwizzlingHelpers.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// NSObject+TLYSwizzlingHelpers.m -// TLYShyNavBarDemo -// -// Created by Mazyad Alabduljaleel on 6/23/14. -// Copyright (c) 2014 Telly, Inc. All rights reserved. -// - -#import "NSObject+TLYSwizzlingHelpers.h" -#import - -@implementation NSObject (TLYSwizzlingHelpers) - -+ (void)tly_swizzleClassMethod:(SEL)originalSelector withReplacement:(SEL)replacementSelector -{ - Method originalMethod = class_getClassMethod([self class], originalSelector); - Method replacementMethod = class_getClassMethod([self class], replacementSelector); - method_exchangeImplementations(replacementMethod, originalMethod); -} - -+ (void)tly_swizzleInstanceMethod:(SEL)originalSelector withReplacement:(SEL)replacementSelector -{ - Method originalMethod = class_getInstanceMethod([self class], originalSelector); - Method replacementMethod = class_getInstanceMethod([self class], replacementSelector); - method_exchangeImplementations(replacementMethod, originalMethod); -} - -@end diff --git a/TLYShyNavBarSwiftDemo/TLYShyNavBar/Categories/UIViewController+BetterLayoutGuides.h b/TLYShyNavBarSwiftDemo/TLYShyNavBar/Categories/UIViewController+BetterLayoutGuides.h deleted file mode 100644 index afd162d..0000000 --- a/TLYShyNavBarSwiftDemo/TLYShyNavBar/Categories/UIViewController+BetterLayoutGuides.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// UIViewController+BetterLayoutGuides.h -// TLYShyNavBarDemo -// -// Created by Mazyad Alabduljaleel on 6/21/14. -// Copyright (c) 2014 Telly, Inc. All rights reserved. -// - -#import - -/* CATEGORY DESCRIPTION: - * ===================== - * Apparently, Apple messed up when they implemented autolayout - * somehow, so when we have child view controllers, they get wrong - * layout guides. This helps accomodate that problem. - * - * Courtesy of http://stackoverflow.com/questions/19140530/toplayoutguide-in-child-view-controller - */ - -@interface UIViewController (BetterLayoutGuides) - -@property (nonatomic, readonly) id tly_topLayoutGuide; -@property (nonatomic, readonly) id tly_bottomLayoutGuide; - -@end diff --git a/TLYShyNavBarSwiftDemo/TLYShyNavBar/Categories/UIViewController+BetterLayoutGuides.m b/TLYShyNavBarSwiftDemo/TLYShyNavBar/Categories/UIViewController+BetterLayoutGuides.m deleted file mode 100644 index 8ea1159..0000000 --- a/TLYShyNavBarSwiftDemo/TLYShyNavBar/Categories/UIViewController+BetterLayoutGuides.m +++ /dev/null @@ -1,37 +0,0 @@ -// -// UIViewController+BetterLayoutGuides.m -// TLYShyNavBarDemo -// -// Created by Mazyad Alabduljaleel on 6/21/14. -// Copyright (c) 2014 Telly, Inc. All rights reserved. -// - -#import "UIViewController+BetterLayoutGuides.h" - -@implementation UIViewController (BetterLayoutGuides) - -- (id)tly_topLayoutGuide -{ - if (self.parentViewController && - ![self.parentViewController isKindOfClass:UINavigationController.class]) - { - return self.parentViewController.tly_topLayoutGuide; - } - else { - return self.topLayoutGuide; - } -} - -- (id)tly_bottomLayoutGuide -{ - if (self.parentViewController && - ![self.parentViewController isKindOfClass:UINavigationController.class]) - { - return self.parentViewController.tly_bottomLayoutGuide; - } - else { - return self.bottomLayoutGuide; - } -} - -@end diff --git a/TLYShyNavBarSwiftDemo/TLYShyNavBar/TLYDelegateProxy.h b/TLYShyNavBarSwiftDemo/TLYShyNavBar/TLYDelegateProxy.h deleted file mode 100644 index fa831eb..0000000 --- a/TLYShyNavBarSwiftDemo/TLYShyNavBar/TLYDelegateProxy.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// TLYDelegateProxy.h -// TLYShyNavBarDemo -// -// Created by Mazyad Alabduljaleel on 6/27/14. -// Copyright (c) 2014 Telly, Inc. All rights reserved. -// - -#import - -/* CLASS DESCRIPTION: - * ================== - * Delegate proxy is meant to be used as a proxy between and - * object and its delegate. The DelegateProxy is initialized with a - * target and middle man, where the target is the original delegate - * and the middle-man is just an object we send identical messages to. - */ - -@interface TLYDelegateProxy : NSProxy - -@property (nonatomic, weak) id originalDelegate; - -- (instancetype)initWithMiddleMan:(id)middleMan; - -@end diff --git a/TLYShyNavBarSwiftDemo/TLYShyNavBar/TLYDelegateProxy.m b/TLYShyNavBarSwiftDemo/TLYShyNavBar/TLYDelegateProxy.m deleted file mode 100644 index 5324fdd..0000000 --- a/TLYShyNavBarSwiftDemo/TLYShyNavBar/TLYDelegateProxy.m +++ /dev/null @@ -1,74 +0,0 @@ -// -// TLYDelegateProxy.m -// TLYShyNavBarDemo -// -// Created by Mazyad Alabduljaleel on 6/27/14. -// Copyright (c) 2014 Telly, Inc. All rights reserved. -// - -#import "TLYDelegateProxy.h" -#import - -@interface TLYDelegateProxy () - -@property (nonatomic, weak) id middleMan; - -@end - -@implementation TLYDelegateProxy - -- (instancetype)initWithMiddleMan:(id)middleMan -{ - if (self) - { - self.middleMan = middleMan; - } - return self; -} - -- (NSInvocation *)_copyInvocation:(NSInvocation *)invocation -{ - NSInvocation *copy = [NSInvocation invocationWithMethodSignature:[invocation methodSignature]]; - NSUInteger argCount = [[invocation methodSignature] numberOfArguments]; - - for (int i = 0; i < argCount; i++) - { - char buffer[sizeof(intmax_t)]; - [invocation getArgument:(void *)&buffer atIndex:i]; - [copy setArgument:(void *)&buffer atIndex:i]; - } - - return copy; -} - -- (void)forwardInvocation:(NSInvocation *)invocation -{ - if ([self.middleMan respondsToSelector:invocation.selector]) - { - NSInvocation *invocationCopy = [self _copyInvocation:invocation]; - [invocationCopy invokeWithTarget:self.middleMan]; - } - - if ([self.originalDelegate respondsToSelector:invocation.selector]) - { - [invocation invokeWithTarget:self.originalDelegate]; - } -} - -- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel -{ - id result = [self.originalDelegate methodSignatureForSelector:sel]; - if (!result) { - result = [self.middleMan methodSignatureForSelector:sel]; - } - - return result; -} - -- (BOOL)respondsToSelector:(SEL)aSelector -{ - return ([self.originalDelegate respondsToSelector:aSelector] - || [self.middleMan respondsToSelector:aSelector]); -} - -@end diff --git a/TLYShyNavBarSwiftDemo/TLYShyNavBar/TLYShyNavBarManager.h b/TLYShyNavBarSwiftDemo/TLYShyNavBar/TLYShyNavBarManager.h deleted file mode 100644 index b4484ab..0000000 --- a/TLYShyNavBarSwiftDemo/TLYShyNavBar/TLYShyNavBarManager.h +++ /dev/null @@ -1,77 +0,0 @@ -// -// TLYShyNavBarManager.h -// TLYShyNavBarDemo -// -// Created by Mazyad Alabduljaleel on 6/13/14. -// Copyright (c) 2014 Telly, Inc. All rights reserved. -// - -#import -#import - -/* CLASS DESCRIPTION: - * ================== - * Manages the relationship between a scrollView and a view - * controller. Must be instantiated and assigned the scrollView - * that drives the contraction/expansion, then assigned to the - * viewController that needs the functionality. Must be assigned - * throught the UIViewController category: - * - * viewController.shyNavManager = ...; - * - */ - -@interface TLYShyNavBarManager : NSObject - -/* The view controller that is part of the navigation stack - * IMPORTANT: Must have access to navigationController - */ -@property (nonatomic, readonly, weak) UIViewController *viewController; - -/* The scrollView subclass that will drive the contraction/expansion - * IMPORTANT: set this property AFTER assigning its delegate, if needed! - */ -@property (nonatomic, weak) UIScrollView *scrollView; - -/* The extension view to be shown beneath the navbar - */ -@property (nonatomic, strong) UIView *extensionView; - -/* The container contains the extension view, if any. Exposed to - * allow the developer to adjust content offset as necessary. - */ -@property (nonatomic, readonly) CGRect extensionViewBounds; - -/* Control the resistance when scrolling up/down before the navbar - * expands/contracts again. - */ -@property (nonatomic) CGFloat expansionResistance; // default 200 -@property (nonatomic) CGFloat contractionResistance; // default 0 - -/* Turn on or off the alpha fade as the navbar contracts/expands. - * Defaults to YES - */ -@property (nonatomic, getter = isAlphaFadeEnabled) BOOL alphaFadeEnabled; - -@property (nonatomic) BOOL disable; - -@end - - -/* CATEGORY DESCRIPTION: - * ===================== - * The category described in the TLYShyNavBarManager usage, and it - * simply uses associated objects to attatch a TLYShyNavBar to the - * designated view controller. - * - * We also perform some swizzling to pass notifications to the - * TLYShyNavBar. Things like, viewDidLayoutSubviews, viewWillAppear and - * Disappear, ... etc. - */ - -@interface UIViewController (ShyNavBar) - -/* Initially, this is nil, but created for you when you access it */ -@property (nonatomic, strong) TLYShyNavBarManager *shyNavBarManager; - -@end diff --git a/TLYShyNavBarSwiftDemo/TLYShyNavBar/TLYShyNavBarManager.m b/TLYShyNavBarSwiftDemo/TLYShyNavBar/TLYShyNavBarManager.m deleted file mode 100644 index 7e6d390..0000000 --- a/TLYShyNavBarSwiftDemo/TLYShyNavBar/TLYShyNavBarManager.m +++ /dev/null @@ -1,452 +0,0 @@ -// -// TLYShyNavBarManager.m -// TLYShyNavBarDemo -// -// Created by Mazyad Alabduljaleel on 6/13/14. -// Copyright (c) 2014 Telly, Inc. All rights reserved. -// - -#import "TLYShyNavBarManager.h" -#import "TLYShyViewController.h" -#import "TLYDelegateProxy.h" - -#import "UIViewController+BetterLayoutGuides.h" -#import "NSObject+TLYSwizzlingHelpers.h" - -#import - -#pragma mark - Helper functions - -// Thanks to SO user, MattDiPasquale -// http://stackoverflow.com/questions/12991935/how-to-programmatically-get-ios-status-bar-height/16598350#16598350 - -static inline CGFloat AACStatusBarHeight() -{ - if ([UIApplication sharedApplication].statusBarHidden) - { - return 0.f; - } - - CGSize statusBarSize = [UIApplication sharedApplication].statusBarFrame.size; - return MIN(statusBarSize.width, statusBarSize.height); -} - -@implementation UIScrollView(Helper) - -// Modify contentInset and scrollIndicatorInsets while preserving visual content offset -- (void)tly_smartSetInsets:(UIEdgeInsets)contentAndScrollIndicatorInsets -{ - if (contentAndScrollIndicatorInsets.top != self.contentInset.top) - { - CGPoint contentOffset = self.contentOffset; - contentOffset.y -= contentAndScrollIndicatorInsets.top - self.contentInset.top; - self.contentOffset = contentOffset; - } - - self.contentInset = self.scrollIndicatorInsets = contentAndScrollIndicatorInsets; -} - -@end - -#pragma mark - TLYShyNavBarManager class - -@interface TLYShyNavBarManager () - -@property (nonatomic, strong) TLYShyViewController *navBarController; -@property (nonatomic, strong) TLYShyViewController *extensionController; - -@property (nonatomic, strong) TLYDelegateProxy *delegateProxy; - -@property (nonatomic, strong) UIView *extensionViewContainer; - -@property (nonatomic) UIEdgeInsets previousScrollInsets; -@property (nonatomic) CGFloat previousYOffset; -@property (nonatomic) CGFloat resistanceConsumed; - -@property (nonatomic, getter = isContracting) BOOL contracting; -@property (nonatomic) BOOL previousContractionState; - -@property (nonatomic, readonly) BOOL isViewControllerVisible; - -@end - -@implementation TLYShyNavBarManager - -#pragma mark - Init & Dealloc - -- (instancetype)init -{ - self = [super init]; - if (self) - { - self.delegateProxy = [[TLYDelegateProxy alloc] initWithMiddleMan:self]; - - self.contracting = NO; - self.previousContractionState = YES; - - self.expansionResistance = 200.f; - self.contractionResistance = 0.f; - - self.alphaFadeEnabled = YES; - - self.previousScrollInsets = UIEdgeInsetsZero; - self.previousYOffset = NAN; - - self.navBarController = [[TLYShyViewController alloc] init]; - self.navBarController.hidesSubviews = YES; - self.navBarController.expandedCenter = ^(UIView *view) - { - return CGPointMake(CGRectGetMidX(view.bounds), - CGRectGetMidY(view.bounds) + AACStatusBarHeight()); - }; - - self.navBarController.contractionAmount = ^(UIView *view) - { - return CGRectGetHeight(view.bounds); - }; - - self.extensionViewContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100.f, 0.f)]; - self.extensionViewContainer.backgroundColor = [UIColor clearColor]; - self.extensionViewContainer.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleBottomMargin; - - self.extensionController = [[TLYShyViewController alloc] init]; - self.extensionController.view = self.extensionViewContainer; - self.extensionController.hidesAfterContraction = YES; - self.extensionController.contractionAmount = ^(UIView *view) - { - return CGRectGetHeight(view.bounds); - }; - - __weak __typeof(self) weakSelf = self; - self.extensionController.expandedCenter = ^(UIView *view) - { - return CGPointMake(CGRectGetMidX(view.bounds), - CGRectGetMidY(view.bounds) + weakSelf.viewController.tly_topLayoutGuide.length); - }; - - self.navBarController.child = self.extensionController; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil]; - } - return self; -} - -- (void)dealloc -{ - // sanity check - if (_scrollView.delegate == _delegateProxy) - { - _scrollView.delegate = _delegateProxy.originalDelegate; - } - - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -#pragma mark - Properties - -- (void)setViewController:(UIViewController *)viewController -{ - _viewController = viewController; - - UIView *navbar = viewController.navigationController.navigationBar; - NSAssert(navbar != nil, @"You are using the component wrong... Please see the README file."); - - [self.extensionViewContainer removeFromSuperview]; - [self.viewController.view addSubview:self.extensionViewContainer]; - - self.navBarController.view = navbar; - - [self layoutViews]; -} - -- (void)setScrollView:(UIScrollView *)scrollView -{ - if (_scrollView.delegate == self.delegateProxy) - { - _scrollView.delegate = self.delegateProxy.originalDelegate; - } - - _scrollView = scrollView; - - if (_scrollView.delegate != self.delegateProxy) - { - self.delegateProxy.originalDelegate = _scrollView.delegate; - _scrollView.delegate = (id)self.delegateProxy; - } - [self cleanup]; - [self layoutViews]; - -} - -- (CGRect)extensionViewBounds -{ - return self.extensionViewContainer.bounds; -} - -- (BOOL)isViewControllerVisible -{ - return self.viewController.isViewLoaded && self.viewController.view.window; -} - -- (void)setDisable:(BOOL)disable -{ - if (disable == _disable) - { - return; - } - - _disable = disable; - - if (!disable) { - self.previousYOffset = self.scrollView.contentOffset.y; - } -} - -#pragma mark - Private methods - -- (BOOL)_shouldHandleScrolling -{ - if (self.disable) - { - return NO; - } - - CGRect scrollFrame = UIEdgeInsetsInsetRect(self.scrollView.bounds, self.scrollView.contentInset); - CGFloat scrollableAmount = self.scrollView.contentSize.height - CGRectGetHeight(scrollFrame); - BOOL scrollViewIsSuffecientlyLong = (scrollableAmount > self.navBarController.totalHeight); - - return (self.isViewControllerVisible && scrollViewIsSuffecientlyLong); -} - -- (void)_handleScrolling -{ - if (![self _shouldHandleScrolling]) - { - return; - } - - if (!isnan(self.previousYOffset)) - { - // 1 - Calculate the delta - CGFloat deltaY = (self.previousYOffset - self.scrollView.contentOffset.y); - - // 2 - Ignore any scrollOffset beyond the bounds - CGFloat start = -self.scrollView.contentInset.top; - if (self.previousYOffset < start) - { - deltaY = MIN(0, deltaY - self.previousYOffset - start); - } - - /* rounding to resolve a dumb issue with the contentOffset value */ - CGFloat end = floorf(self.scrollView.contentSize.height - CGRectGetHeight(self.scrollView.bounds) + self.scrollView.contentInset.bottom - 0.5f); - if (self.previousYOffset > end && deltaY > 0) - { - deltaY = MAX(0, deltaY - self.previousYOffset + end); - } - - // 3 - Update contracting variable - if (fabs(deltaY) > FLT_EPSILON) - { - self.contracting = deltaY < 0; - } - - // 4 - Check if contracting state changed, and do stuff if so - if (self.isContracting != self.previousContractionState) - { - self.previousContractionState = self.isContracting; - self.resistanceConsumed = 0; - } - - // 5 - Apply resistance - if (self.isContracting) - { - CGFloat availableResistance = self.contractionResistance - self.resistanceConsumed; - self.resistanceConsumed = MIN(self.contractionResistance, self.resistanceConsumed - deltaY); - - deltaY = MIN(0, availableResistance + deltaY); - } - else if (self.scrollView.contentOffset.y > -AACStatusBarHeight()) - { - CGFloat availableResistance = self.expansionResistance - self.resistanceConsumed; - self.resistanceConsumed = MIN(self.expansionResistance, self.resistanceConsumed + deltaY); - - deltaY = MAX(0, deltaY - availableResistance); - } - - // 6 - Update the shyViewController - self.navBarController.alphaFadeEnabled = self.alphaFadeEnabled; - [self.navBarController updateYOffset:deltaY]; - } - - self.previousYOffset = self.scrollView.contentOffset.y; -} - -- (void)_handleScrollingEnded -{ - if (!self.isViewControllerVisible) - { - return; - } - - self.resistanceConsumed = 0; - - CGFloat deltaY = [self.navBarController snap:self.isContracting]; - CGPoint newContentOffset = self.scrollView.contentOffset; - - newContentOffset.y -= deltaY; - - [UIView animateWithDuration:0.2 - animations:^{ - self.scrollView.contentOffset = newContentOffset; - }]; -} - -#pragma mark - public methods - -- (void)setExtensionView:(UIView *)view -{ - if (view != _extensionView) - { - [_extensionView removeFromSuperview]; - _extensionView = view; - - CGRect bounds = view.frame; - bounds.origin = CGPointZero; - - view.frame = bounds; - - self.extensionViewContainer.frame = bounds; - [self.extensionViewContainer addSubview:view]; - - [self layoutViews]; - } -} - -- (void)prepareForDisplay -{ - [self cleanup]; -} - -- (void)layoutViews -{ - UIEdgeInsets scrollInsets = self.scrollView.contentInset; - scrollInsets.top = CGRectGetHeight(self.extensionViewContainer.bounds) + self.viewController.tly_topLayoutGuide.length; - - if (UIEdgeInsetsEqualToEdgeInsets(scrollInsets, self.previousScrollInsets)) - { - return; - } - - self.previousScrollInsets = scrollInsets; - - [self.navBarController expand]; - [self.extensionViewContainer.superview bringSubviewToFront:self.extensionViewContainer]; - - [self.scrollView tly_smartSetInsets:scrollInsets]; -} - -- (void)cleanup -{ - [self.navBarController expand]; - - self.previousYOffset = NAN; - self.previousScrollInsets = UIEdgeInsetsZero; -} - -#pragma mark - UIScrollViewDelegate methods - -- (void)scrollViewDidScroll:(UIScrollView *)scrollView -{ - [self _handleScrolling]; -} - -- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate -{ - if (!decelerate) - { - [self _handleScrollingEnded]; - } -} - -- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView -{ - [self _handleScrollingEnded]; -} - -#pragma mark - NSNotificationCenter methods - -- (void)applicationDidBecomeActive -{ - [self.navBarController expand]; -} - -@end - -#pragma mark - UIViewController+TLYShyNavBar category - -static char shyNavBarManagerKey; - -@implementation UIViewController (ShyNavBar) - -#pragma mark - Static methods - -+ (void)load -{ - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [self tly_swizzleInstanceMethod:@selector(viewWillAppear:) withReplacement:@selector(tly_swizzledViewWillAppear:)]; - [self tly_swizzleInstanceMethod:@selector(viewWillLayoutSubviews) withReplacement:@selector(tly_swizzledViewDidLayoutSubviews)]; - [self tly_swizzleInstanceMethod:@selector(viewWillDisappear:) withReplacement:@selector(tly_swizzledViewWillDisappear:)]; - }); -} - -#pragma mark - Swizzled View Life Cycle - -- (void)tly_swizzledViewWillAppear:(BOOL)animated -{ - [[self _internalShyNavBarManager] prepareForDisplay]; - [self tly_swizzledViewWillAppear:animated]; -} - -- (void)tly_swizzledViewDidLayoutSubviews -{ - [[self _internalShyNavBarManager] layoutViews]; - [self tly_swizzledViewDidLayoutSubviews]; -} - -- (void)tly_swizzledViewWillDisappear:(BOOL)animated -{ - [[self _internalShyNavBarManager] cleanup]; - [self tly_swizzledViewWillDisappear:animated]; -} - -#pragma mark - Properties - -- (void)setShyNavBarManager:(TLYShyNavBarManager *)shyNavBarManager -{ - shyNavBarManager.viewController = self; - objc_setAssociatedObject(self, ­NavBarManagerKey, shyNavBarManager, OBJC_ASSOCIATION_RETAIN_NONATOMIC); -} - -- (TLYShyNavBarManager *)shyNavBarManager -{ - id shyNavBarManager = objc_getAssociatedObject(self, ­NavBarManagerKey); - if (!shyNavBarManager) - { - shyNavBarManager = [[TLYShyNavBarManager alloc] init]; - self.shyNavBarManager = shyNavBarManager; - } - - return shyNavBarManager; -} - -#pragma mark - Private methods - -/* Internally, we need to access the variable without creating it */ -- (TLYShyNavBarManager *)_internalShyNavBarManager -{ - return objc_getAssociatedObject(self, ­NavBarManagerKey); -} - -@end - diff --git a/TLYShyNavBarSwiftDemo/TLYShyNavBar/TLYShyViewController.h b/TLYShyNavBarSwiftDemo/TLYShyNavBar/TLYShyViewController.h deleted file mode 100644 index 021d981..0000000 --- a/TLYShyNavBarSwiftDemo/TLYShyNavBar/TLYShyViewController.h +++ /dev/null @@ -1,50 +0,0 @@ -// -// TLYShyViewController.h -// TLYShyNavBarDemo -// -// Created by Mazyad Alabduljaleel on 6/14/14. -// Copyright (c) 2014 Telly, Inc. All rights reserved. -// - -#import -#import - -extern const CGFloat contractionVelocity; - -typedef CGPoint(^TLYShyViewControllerExpandedCenterBlock)(UIView *view); -typedef CGFloat(^TLYShyViewControllerContractionAmountBlock)(UIView *view); - -/* CLASS DESCRIPTION: - * ================== - * A shy view is a view that contracts when a scrolling event is - * triggered. We use this class to control the operations we perform on - * the shy view. - * - * We are making some dangerous assumtions here!!! Most importantly, - * the TLYShyViewController can only be a maximum depth of 2. Adding a - * child to an already childified node is not supported. - */ - -@interface TLYShyViewController : NSObject - -@property (nonatomic, weak) TLYShyViewController *child; -@property (nonatomic, weak) UIView *view; - -@property (nonatomic, copy) TLYShyViewControllerExpandedCenterBlock expandedCenter; -@property (nonatomic, copy) TLYShyViewControllerContractionAmountBlock contractionAmount; - -@property (nonatomic) BOOL hidesSubviews; -@property (nonatomic) BOOL hidesAfterContraction; - -@property (nonatomic) BOOL alphaFadeEnabled; - -@property (nonatomic, readonly) CGFloat totalHeight; - -- (CGFloat)updateYOffset:(CGFloat)deltaY; - -- (CGFloat)snap:(BOOL)contract; - -- (CGFloat)expand; -- (CGFloat)contract; - -@end diff --git a/TLYShyNavBarSwiftDemo/TLYShyNavBar/TLYShyViewController.m b/TLYShyNavBarSwiftDemo/TLYShyNavBar/TLYShyViewController.m deleted file mode 100644 index 1fb0369..0000000 --- a/TLYShyNavBarSwiftDemo/TLYShyNavBar/TLYShyViewController.m +++ /dev/null @@ -1,181 +0,0 @@ -// -// TLYShyViewController.m -// TLYShyNavBarDemo -// -// Created by Mazyad Alabduljaleel on 6/14/14. -// Copyright (c) 2014 Telly, Inc. All rights reserved. -// - -#import "TLYShyViewController.h" - -const CGFloat contractionVelocity = 300.f; - -@interface TLYShyViewController () - -@property (nonatomic) CGPoint expandedCenterValue; -@property (nonatomic) CGFloat contractionAmountValue; - -@property (nonatomic) CGPoint contractedCenterValue; - -@property (nonatomic, getter = isContracted) BOOL contracted; -@property (nonatomic, getter = isExpanded) BOOL expanded; - -@end - -@implementation TLYShyViewController - -#pragma mark - Properties - -// convenience -- (CGPoint)expandedCenterValue -{ - return self.expandedCenter(self.view); -} - -- (CGFloat)contractionAmountValue -{ - return self.contractionAmount(self.view); -} - -- (CGPoint)contractedCenterValue -{ - return CGPointMake(self.expandedCenterValue.x, self.expandedCenterValue.y - self.contractionAmountValue); -} - -- (BOOL)isContracted -{ - return fabs(self.view.center.y - self.contractedCenterValue.y) < FLT_EPSILON; -} - -- (BOOL)isExpanded -{ - return fabs(self.view.center.y - self.expandedCenterValue.y) < FLT_EPSILON; -} - -- (CGFloat)totalHeight -{ - return self.child.totalHeight + (self.expandedCenterValue.y - self.contractedCenterValue.y); -} - -#pragma mark - Private methods - -// This method is courtesy of GTScrollNavigationBar -// https://github.com/luugiathuy/GTScrollNavigationBar -- (void)_updateSubviewsToAlpha:(CGFloat)alpha -{ - for (UIView* view in self.view.subviews) - { - bool isBackgroundView = view == self.view.subviews[0]; - bool isViewHidden = view.hidden || view.alpha < FLT_EPSILON; - - if (!isBackgroundView && !isViewHidden) - { - view.alpha = alpha; - } - } -} - -#pragma mark - Public methods - -- (void)setAlphaFadeEnabled:(BOOL)alphaFadeEnabled -{ - _alphaFadeEnabled = alphaFadeEnabled; - - if (!alphaFadeEnabled) - { - [self _updateSubviewsToAlpha:1.f]; - } -} - -- (CGFloat)updateYOffset:(CGFloat)deltaY -{ - if (self.child && deltaY < 0) - { - deltaY = [self.child updateYOffset:deltaY]; - self.child.view.hidden = (deltaY) < 0; - } - - CGFloat newYOffset = self.view.center.y + deltaY; - CGFloat newYCenter = MAX(MIN(self.expandedCenterValue.y, newYOffset), self.contractedCenterValue.y); - - self.view.center = CGPointMake(self.expandedCenterValue.x, newYCenter); - - if (self.hidesSubviews) - { - CGFloat newAlpha = 1.f - (self.expandedCenterValue.y - self.view.center.y) / self.contractionAmountValue; - newAlpha = MIN(MAX(FLT_EPSILON, newAlpha), 1.f); - - if (self.alphaFadeEnabled) - { - [self _updateSubviewsToAlpha:newAlpha]; - } - } - - CGFloat residual = newYOffset - newYCenter; - - if (self.child && deltaY > 0 && residual > 0) - { - residual = [self.child updateYOffset:residual]; - self.child.view.hidden = residual - (newYOffset - newYCenter) > 0; - } - - return residual; -} - -- (CGFloat)snap:(BOOL)contract -{ - /* "The Facebook" UX dictates that: - * - * 1 - When you contract: - * A - contract beyond the extension view -> contract the whole thing - * B - contract within the extension view -> expand the extension back - * - * 2 - When you expand: - * A - expand beyond the navbar -> expand the whole thing - * B - expand within the navbar -> contract the navbar back - */ - - __block CGFloat deltaY; - [UIView animateWithDuration:0.2 animations:^ - { - if ((contract && self.child.isContracted) || (!contract && !self.isExpanded)) - { - deltaY = [self contract]; - } - else - { - deltaY = [self.child expand]; - } - }]; - - return deltaY; -} - -- (CGFloat)expand -{ - self.view.hidden = NO; - - if (self.hidesSubviews && self.alphaFadeEnabled) - { - [self _updateSubviewsToAlpha:1.f]; - } - - CGFloat amountToMove = self.expandedCenterValue.y - self.view.center.y; - - self.view.center = self.expandedCenterValue; - [self.child expand]; - - return amountToMove; -} - -- (CGFloat)contract -{ - CGFloat amountToMove = self.contractedCenterValue.y - self.view.center.y; - - self.view.center = self.contractedCenterValue; - [self.child contract]; - - return amountToMove; -} - -@end diff --git a/TLYShyNavBarSwiftDemo/TLYShyNavBarSwiftDemo.xcodeproj/project.pbxproj b/TLYShyNavBarSwiftDemo/TLYShyNavBarSwiftDemo.xcodeproj/project.pbxproj index 38e2ce7..b97cd3b 100644 --- a/TLYShyNavBarSwiftDemo/TLYShyNavBarSwiftDemo.xcodeproj/project.pbxproj +++ b/TLYShyNavBarSwiftDemo/TLYShyNavBarSwiftDemo.xcodeproj/project.pbxproj @@ -12,12 +12,12 @@ E7ADE6171A99A83B00E8F95C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E7ADE6161A99A83B00E8F95C /* Images.xcassets */; }; E7ADE61A1A99A83B00E8F95C /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = E7ADE6181A99A83B00E8F95C /* LaunchScreen.xib */; }; E7ADE6261A99A83B00E8F95C /* TLYShyNavBarSwiftDemoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7ADE6251A99A83B00E8F95C /* TLYShyNavBarSwiftDemoTests.swift */; }; - E7ADE63B1A99A84C00E8F95C /* NSObject+TLYSwizzlingHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = E7ADE6321A99A84C00E8F95C /* NSObject+TLYSwizzlingHelpers.m */; }; - E7ADE63C1A99A84C00E8F95C /* UIViewController+BetterLayoutGuides.m in Sources */ = {isa = PBXBuildFile; fileRef = E7ADE6341A99A84C00E8F95C /* UIViewController+BetterLayoutGuides.m */; }; - E7ADE63D1A99A84C00E8F95C /* TLYDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = E7ADE6361A99A84C00E8F95C /* TLYDelegateProxy.m */; }; - E7ADE63E1A99A84C00E8F95C /* TLYShyNavBarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E7ADE6381A99A84C00E8F95C /* TLYShyNavBarManager.m */; }; - E7ADE63F1A99A84C00E8F95C /* TLYShyViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E7ADE63A1A99A84C00E8F95C /* TLYShyViewController.m */; }; E7ADE6421A99AB5800E8F95C /* TableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7ADE6411A99AB5800E8F95C /* TableViewController.swift */; }; + E7ADE64F1A9A6F7C00E8F95C /* NSObject+TLYSwizzlingHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = E7ADE6461A9A6F7C00E8F95C /* NSObject+TLYSwizzlingHelpers.m */; }; + E7ADE6501A9A6F7C00E8F95C /* UIViewController+BetterLayoutGuides.m in Sources */ = {isa = PBXBuildFile; fileRef = E7ADE6481A9A6F7C00E8F95C /* UIViewController+BetterLayoutGuides.m */; }; + E7ADE6511A9A6F7C00E8F95C /* TLYDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = E7ADE64A1A9A6F7C00E8F95C /* TLYDelegateProxy.m */; }; + E7ADE6521A9A6F7C00E8F95C /* TLYShyNavBarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E7ADE64C1A9A6F7C00E8F95C /* TLYShyNavBarManager.m */; }; + E7ADE6531A9A6F7C00E8F95C /* TLYShyViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E7ADE64E1A9A6F7C00E8F95C /* TLYShyViewController.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -40,18 +40,18 @@ E7ADE61F1A99A83B00E8F95C /* TLYShyNavBarSwiftDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TLYShyNavBarSwiftDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; E7ADE6241A99A83B00E8F95C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E7ADE6251A99A83B00E8F95C /* TLYShyNavBarSwiftDemoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TLYShyNavBarSwiftDemoTests.swift; sourceTree = ""; }; - E7ADE6311A99A84C00E8F95C /* NSObject+TLYSwizzlingHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+TLYSwizzlingHelpers.h"; sourceTree = ""; }; - E7ADE6321A99A84C00E8F95C /* NSObject+TLYSwizzlingHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+TLYSwizzlingHelpers.m"; sourceTree = ""; }; - E7ADE6331A99A84C00E8F95C /* UIViewController+BetterLayoutGuides.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+BetterLayoutGuides.h"; sourceTree = ""; }; - E7ADE6341A99A84C00E8F95C /* UIViewController+BetterLayoutGuides.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+BetterLayoutGuides.m"; sourceTree = ""; }; - E7ADE6351A99A84C00E8F95C /* TLYDelegateProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLYDelegateProxy.h; sourceTree = ""; }; - E7ADE6361A99A84C00E8F95C /* TLYDelegateProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLYDelegateProxy.m; sourceTree = ""; }; - E7ADE6371A99A84C00E8F95C /* TLYShyNavBarManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLYShyNavBarManager.h; sourceTree = ""; }; - E7ADE6381A99A84C00E8F95C /* TLYShyNavBarManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLYShyNavBarManager.m; sourceTree = ""; }; - E7ADE6391A99A84C00E8F95C /* TLYShyViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLYShyViewController.h; sourceTree = ""; }; - E7ADE63A1A99A84C00E8F95C /* TLYShyViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLYShyViewController.m; sourceTree = ""; }; E7ADE6401A99A86600E8F95C /* Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = ""; }; E7ADE6411A99AB5800E8F95C /* TableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewController.swift; sourceTree = ""; }; + E7ADE6451A9A6F7C00E8F95C /* NSObject+TLYSwizzlingHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+TLYSwizzlingHelpers.h"; sourceTree = ""; }; + E7ADE6461A9A6F7C00E8F95C /* NSObject+TLYSwizzlingHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+TLYSwizzlingHelpers.m"; sourceTree = ""; }; + E7ADE6471A9A6F7C00E8F95C /* UIViewController+BetterLayoutGuides.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+BetterLayoutGuides.h"; sourceTree = ""; }; + E7ADE6481A9A6F7C00E8F95C /* UIViewController+BetterLayoutGuides.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+BetterLayoutGuides.m"; sourceTree = ""; }; + E7ADE6491A9A6F7C00E8F95C /* TLYDelegateProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLYDelegateProxy.h; sourceTree = ""; }; + E7ADE64A1A9A6F7C00E8F95C /* TLYDelegateProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLYDelegateProxy.m; sourceTree = ""; }; + E7ADE64B1A9A6F7C00E8F95C /* TLYShyNavBarManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLYShyNavBarManager.h; sourceTree = ""; }; + E7ADE64C1A9A6F7C00E8F95C /* TLYShyNavBarManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLYShyNavBarManager.m; sourceTree = ""; }; + E7ADE64D1A9A6F7C00E8F95C /* TLYShyViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLYShyViewController.h; sourceTree = ""; }; + E7ADE64E1A9A6F7C00E8F95C /* TLYShyViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLYShyViewController.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -76,7 +76,7 @@ isa = PBXGroup; children = ( E7ADE6401A99A86600E8F95C /* Bridging-Header.h */, - E7ADE62F1A99A84C00E8F95C /* TLYShyNavBar */, + E7ADE6431A9A6F7C00E8F95C /* TLYShyNavBar */, E7ADE60C1A99A83B00E8F95C /* TLYShyNavBarSwiftDemo */, E7ADE6221A99A83B00E8F95C /* TLYShyNavBarSwiftDemoTests */, E7ADE60B1A99A83B00E8F95C /* Products */, @@ -130,27 +130,28 @@ name = "Supporting Files"; sourceTree = ""; }; - E7ADE62F1A99A84C00E8F95C /* TLYShyNavBar */ = { + E7ADE6431A9A6F7C00E8F95C /* TLYShyNavBar */ = { isa = PBXGroup; children = ( - E7ADE6301A99A84C00E8F95C /* Categories */, - E7ADE6351A99A84C00E8F95C /* TLYDelegateProxy.h */, - E7ADE6361A99A84C00E8F95C /* TLYDelegateProxy.m */, - E7ADE6371A99A84C00E8F95C /* TLYShyNavBarManager.h */, - E7ADE6381A99A84C00E8F95C /* TLYShyNavBarManager.m */, - E7ADE6391A99A84C00E8F95C /* TLYShyViewController.h */, - E7ADE63A1A99A84C00E8F95C /* TLYShyViewController.m */, + E7ADE6441A9A6F7C00E8F95C /* Categories */, + E7ADE6491A9A6F7C00E8F95C /* TLYDelegateProxy.h */, + E7ADE64A1A9A6F7C00E8F95C /* TLYDelegateProxy.m */, + E7ADE64B1A9A6F7C00E8F95C /* TLYShyNavBarManager.h */, + E7ADE64C1A9A6F7C00E8F95C /* TLYShyNavBarManager.m */, + E7ADE64D1A9A6F7C00E8F95C /* TLYShyViewController.h */, + E7ADE64E1A9A6F7C00E8F95C /* TLYShyViewController.m */, ); - path = TLYShyNavBar; + name = TLYShyNavBar; + path = ../TLYShyNavBar; sourceTree = ""; }; - E7ADE6301A99A84C00E8F95C /* Categories */ = { + E7ADE6441A9A6F7C00E8F95C /* Categories */ = { isa = PBXGroup; children = ( - E7ADE6311A99A84C00E8F95C /* NSObject+TLYSwizzlingHelpers.h */, - E7ADE6321A99A84C00E8F95C /* NSObject+TLYSwizzlingHelpers.m */, - E7ADE6331A99A84C00E8F95C /* UIViewController+BetterLayoutGuides.h */, - E7ADE6341A99A84C00E8F95C /* UIViewController+BetterLayoutGuides.m */, + E7ADE6451A9A6F7C00E8F95C /* NSObject+TLYSwizzlingHelpers.h */, + E7ADE6461A9A6F7C00E8F95C /* NSObject+TLYSwizzlingHelpers.m */, + E7ADE6471A9A6F7C00E8F95C /* UIViewController+BetterLayoutGuides.h */, + E7ADE6481A9A6F7C00E8F95C /* UIViewController+BetterLayoutGuides.m */, ); path = Categories; sourceTree = ""; @@ -255,13 +256,13 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - E7ADE63F1A99A84C00E8F95C /* TLYShyViewController.m in Sources */, - E7ADE63C1A99A84C00E8F95C /* UIViewController+BetterLayoutGuides.m in Sources */, + E7ADE6531A9A6F7C00E8F95C /* TLYShyViewController.m in Sources */, E7ADE6421A99AB5800E8F95C /* TableViewController.swift in Sources */, + E7ADE6501A9A6F7C00E8F95C /* UIViewController+BetterLayoutGuides.m in Sources */, E7ADE6101A99A83B00E8F95C /* AppDelegate.swift in Sources */, - E7ADE63D1A99A84C00E8F95C /* TLYDelegateProxy.m in Sources */, - E7ADE63E1A99A84C00E8F95C /* TLYShyNavBarManager.m in Sources */, - E7ADE63B1A99A84C00E8F95C /* NSObject+TLYSwizzlingHelpers.m in Sources */, + E7ADE6511A9A6F7C00E8F95C /* TLYDelegateProxy.m in Sources */, + E7ADE6521A9A6F7C00E8F95C /* TLYShyNavBarManager.m in Sources */, + E7ADE64F1A9A6F7C00E8F95C /* NSObject+TLYSwizzlingHelpers.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -455,6 +456,7 @@ E7ADE62B1A99A83B00E8F95C /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; E7ADE62C1A99A83B00E8F95C /* Build configuration list for PBXNativeTarget "TLYShyNavBarSwiftDemoTests" */ = { isa = XCConfigurationList; @@ -463,6 +465,7 @@ E7ADE62E1A99A83B00E8F95C /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ };