Adding Swift code example

This commit is contained in:
Tony Nuzzi 2015-02-22 00:23:09 -06:00
parent c4fbbb674c
commit b2c040fb1e
24 changed files with 1834 additions and 0 deletions

View File

@ -14,6 +14,11 @@
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
}
],
"info" : {

View File

@ -8,6 +8,10 @@
"idiom" : "universal",
"scale" : "2x",
"filename" : "sample@2x.png"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {

View File

@ -0,0 +1,16 @@
//
// Bridging-Header.h
// TLYShyNavBarSwiftDemo
//
// Created by Tony Nuzzi on 2/22/15.
// Copyright (c) 2015 Acktie, LLC. All rights reserved.
//
#ifndef TLYShyNavBarSwiftDemo_Bridging_Header_h
#define TLYShyNavBarSwiftDemo_Bridging_Header_h
#import "TLYShyNavBarManager.h"
#import "TLYShyViewController.h"
#import "TLYDelegateProxy.h"
#import "NSObject+TLYSwizzlingHelpers.h"
#import "UIViewController+BetterLayoutGuides.h"
#endif

View File

@ -0,0 +1,16 @@
//
// NSObject+TLYSwizzlingHelpers.h
// TLYShyNavBarDemo
//
// Created by Mazyad Alabduljaleel on 6/23/14.
// Copyright (c) 2014 Telly, Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSObject (TLYSwizzlingHelpers)
+ (void)tly_swizzleClassMethod:(SEL)originalSelector withReplacement:(SEL)replacementSelector;
+ (void)tly_swizzleInstanceMethod:(SEL)originalSelector withReplacement:(SEL)replacementSelector;
@end

View File

@ -0,0 +1,28 @@
//
// 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 <objc/runtime.h>
@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

View File

@ -0,0 +1,25 @@
//
// UIViewController+BetterLayoutGuides.h
// TLYShyNavBarDemo
//
// Created by Mazyad Alabduljaleel on 6/21/14.
// Copyright (c) 2014 Telly, Inc. All rights reserved.
//
#import <UIKit/UIKit.h>
/* 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<UILayoutSupport> tly_topLayoutGuide;
@property (nonatomic, readonly) id<UILayoutSupport> tly_bottomLayoutGuide;
@end

View File

@ -0,0 +1,37 @@
//
// 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<UILayoutSupport>)tly_topLayoutGuide
{
if (self.parentViewController &&
![self.parentViewController isKindOfClass:UINavigationController.class])
{
return self.parentViewController.tly_topLayoutGuide;
}
else {
return self.topLayoutGuide;
}
}
- (id<UILayoutSupport>)tly_bottomLayoutGuide
{
if (self.parentViewController &&
![self.parentViewController isKindOfClass:UINavigationController.class])
{
return self.parentViewController.tly_bottomLayoutGuide;
}
else {
return self.bottomLayoutGuide;
}
}
@end

View File

@ -0,0 +1,25 @@
//
// TLYDelegateProxy.h
// TLYShyNavBarDemo
//
// Created by Mazyad Alabduljaleel on 6/27/14.
// Copyright (c) 2014 Telly, Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
/* 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

View File

@ -0,0 +1,74 @@
//
// TLYDelegateProxy.m
// TLYShyNavBarDemo
//
// Created by Mazyad Alabduljaleel on 6/27/14.
// Copyright (c) 2014 Telly, Inc. All rights reserved.
//
#import "TLYDelegateProxy.h"
#import <objc/runtime.h>
@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

View File

@ -0,0 +1,77 @@
//
// TLYShyNavBarManager.h
// TLYShyNavBarDemo
//
// Created by Mazyad Alabduljaleel on 6/13/14.
// Copyright (c) 2014 Telly, Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
/* 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

View File

@ -0,0 +1,452 @@
//
// 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 <objc/runtime.h>
#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 () <UIScrollViewDelegate>
@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, &shyNavBarManagerKey, shyNavBarManager, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (TLYShyNavBarManager *)shyNavBarManager
{
id shyNavBarManager = objc_getAssociatedObject(self, &shyNavBarManagerKey);
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, &shyNavBarManagerKey);
}
@end

View File

@ -0,0 +1,50 @@
//
// TLYShyViewController.h
// TLYShyNavBarDemo
//
// Created by Mazyad Alabduljaleel on 6/14/14.
// Copyright (c) 2014 Telly, Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
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

View File

@ -0,0 +1,181 @@
//
// 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

View File

@ -0,0 +1,470 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
E7ADE6101A99A83B00E8F95C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7ADE60F1A99A83B00E8F95C /* AppDelegate.swift */; };
E7ADE6151A99A83B00E8F95C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E7ADE6131A99A83B00E8F95C /* Main.storyboard */; };
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 */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
E7ADE6201A99A83B00E8F95C /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = E7ADE6021A99A83B00E8F95C /* Project object */;
proxyType = 1;
remoteGlobalIDString = E7ADE6091A99A83B00E8F95C;
remoteInfo = TLYShyNavBarSwiftDemo;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
E7ADE60A1A99A83B00E8F95C /* TLYShyNavBarSwiftDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TLYShyNavBarSwiftDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
E7ADE60E1A99A83B00E8F95C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
E7ADE60F1A99A83B00E8F95C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
E7ADE6141A99A83B00E8F95C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
E7ADE6161A99A83B00E8F95C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
E7ADE6191A99A83B00E8F95C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
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 = "<group>"; };
E7ADE6251A99A83B00E8F95C /* TLYShyNavBarSwiftDemoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TLYShyNavBarSwiftDemoTests.swift; sourceTree = "<group>"; };
E7ADE6311A99A84C00E8F95C /* NSObject+TLYSwizzlingHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+TLYSwizzlingHelpers.h"; sourceTree = "<group>"; };
E7ADE6321A99A84C00E8F95C /* NSObject+TLYSwizzlingHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+TLYSwizzlingHelpers.m"; sourceTree = "<group>"; };
E7ADE6331A99A84C00E8F95C /* UIViewController+BetterLayoutGuides.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+BetterLayoutGuides.h"; sourceTree = "<group>"; };
E7ADE6341A99A84C00E8F95C /* UIViewController+BetterLayoutGuides.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+BetterLayoutGuides.m"; sourceTree = "<group>"; };
E7ADE6351A99A84C00E8F95C /* TLYDelegateProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLYDelegateProxy.h; sourceTree = "<group>"; };
E7ADE6361A99A84C00E8F95C /* TLYDelegateProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLYDelegateProxy.m; sourceTree = "<group>"; };
E7ADE6371A99A84C00E8F95C /* TLYShyNavBarManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLYShyNavBarManager.h; sourceTree = "<group>"; };
E7ADE6381A99A84C00E8F95C /* TLYShyNavBarManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLYShyNavBarManager.m; sourceTree = "<group>"; };
E7ADE6391A99A84C00E8F95C /* TLYShyViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLYShyViewController.h; sourceTree = "<group>"; };
E7ADE63A1A99A84C00E8F95C /* TLYShyViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLYShyViewController.m; sourceTree = "<group>"; };
E7ADE6401A99A86600E8F95C /* Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = "<group>"; };
E7ADE6411A99AB5800E8F95C /* TableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewController.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
E7ADE6071A99A83B00E8F95C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
E7ADE61C1A99A83B00E8F95C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
E7ADE6011A99A83B00E8F95C = {
isa = PBXGroup;
children = (
E7ADE6401A99A86600E8F95C /* Bridging-Header.h */,
E7ADE62F1A99A84C00E8F95C /* TLYShyNavBar */,
E7ADE60C1A99A83B00E8F95C /* TLYShyNavBarSwiftDemo */,
E7ADE6221A99A83B00E8F95C /* TLYShyNavBarSwiftDemoTests */,
E7ADE60B1A99A83B00E8F95C /* Products */,
);
sourceTree = "<group>";
};
E7ADE60B1A99A83B00E8F95C /* Products */ = {
isa = PBXGroup;
children = (
E7ADE60A1A99A83B00E8F95C /* TLYShyNavBarSwiftDemo.app */,
E7ADE61F1A99A83B00E8F95C /* TLYShyNavBarSwiftDemoTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
E7ADE60C1A99A83B00E8F95C /* TLYShyNavBarSwiftDemo */ = {
isa = PBXGroup;
children = (
E7ADE60F1A99A83B00E8F95C /* AppDelegate.swift */,
E7ADE6131A99A83B00E8F95C /* Main.storyboard */,
E7ADE6411A99AB5800E8F95C /* TableViewController.swift */,
E7ADE6161A99A83B00E8F95C /* Images.xcassets */,
E7ADE6181A99A83B00E8F95C /* LaunchScreen.xib */,
E7ADE60D1A99A83B00E8F95C /* Supporting Files */,
);
path = TLYShyNavBarSwiftDemo;
sourceTree = "<group>";
};
E7ADE60D1A99A83B00E8F95C /* Supporting Files */ = {
isa = PBXGroup;
children = (
E7ADE60E1A99A83B00E8F95C /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
E7ADE6221A99A83B00E8F95C /* TLYShyNavBarSwiftDemoTests */ = {
isa = PBXGroup;
children = (
E7ADE6251A99A83B00E8F95C /* TLYShyNavBarSwiftDemoTests.swift */,
E7ADE6231A99A83B00E8F95C /* Supporting Files */,
);
path = TLYShyNavBarSwiftDemoTests;
sourceTree = "<group>";
};
E7ADE6231A99A83B00E8F95C /* Supporting Files */ = {
isa = PBXGroup;
children = (
E7ADE6241A99A83B00E8F95C /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
E7ADE62F1A99A84C00E8F95C /* TLYShyNavBar */ = {
isa = PBXGroup;
children = (
E7ADE6301A99A84C00E8F95C /* Categories */,
E7ADE6351A99A84C00E8F95C /* TLYDelegateProxy.h */,
E7ADE6361A99A84C00E8F95C /* TLYDelegateProxy.m */,
E7ADE6371A99A84C00E8F95C /* TLYShyNavBarManager.h */,
E7ADE6381A99A84C00E8F95C /* TLYShyNavBarManager.m */,
E7ADE6391A99A84C00E8F95C /* TLYShyViewController.h */,
E7ADE63A1A99A84C00E8F95C /* TLYShyViewController.m */,
);
path = TLYShyNavBar;
sourceTree = "<group>";
};
E7ADE6301A99A84C00E8F95C /* Categories */ = {
isa = PBXGroup;
children = (
E7ADE6311A99A84C00E8F95C /* NSObject+TLYSwizzlingHelpers.h */,
E7ADE6321A99A84C00E8F95C /* NSObject+TLYSwizzlingHelpers.m */,
E7ADE6331A99A84C00E8F95C /* UIViewController+BetterLayoutGuides.h */,
E7ADE6341A99A84C00E8F95C /* UIViewController+BetterLayoutGuides.m */,
);
path = Categories;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
E7ADE6091A99A83B00E8F95C /* TLYShyNavBarSwiftDemo */ = {
isa = PBXNativeTarget;
buildConfigurationList = E7ADE6291A99A83B00E8F95C /* Build configuration list for PBXNativeTarget "TLYShyNavBarSwiftDemo" */;
buildPhases = (
E7ADE6061A99A83B00E8F95C /* Sources */,
E7ADE6071A99A83B00E8F95C /* Frameworks */,
E7ADE6081A99A83B00E8F95C /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = TLYShyNavBarSwiftDemo;
productName = TLYShyNavBarSwiftDemo;
productReference = E7ADE60A1A99A83B00E8F95C /* TLYShyNavBarSwiftDemo.app */;
productType = "com.apple.product-type.application";
};
E7ADE61E1A99A83B00E8F95C /* TLYShyNavBarSwiftDemoTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = E7ADE62C1A99A83B00E8F95C /* Build configuration list for PBXNativeTarget "TLYShyNavBarSwiftDemoTests" */;
buildPhases = (
E7ADE61B1A99A83B00E8F95C /* Sources */,
E7ADE61C1A99A83B00E8F95C /* Frameworks */,
E7ADE61D1A99A83B00E8F95C /* Resources */,
);
buildRules = (
);
dependencies = (
E7ADE6211A99A83B00E8F95C /* PBXTargetDependency */,
);
name = TLYShyNavBarSwiftDemoTests;
productName = TLYShyNavBarSwiftDemoTests;
productReference = E7ADE61F1A99A83B00E8F95C /* TLYShyNavBarSwiftDemoTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
E7ADE6021A99A83B00E8F95C /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0610;
ORGANIZATIONNAME = "Acktie, LLC";
TargetAttributes = {
E7ADE6091A99A83B00E8F95C = {
CreatedOnToolsVersion = 6.1.1;
};
E7ADE61E1A99A83B00E8F95C = {
CreatedOnToolsVersion = 6.1.1;
TestTargetID = E7ADE6091A99A83B00E8F95C;
};
};
};
buildConfigurationList = E7ADE6051A99A83B00E8F95C /* Build configuration list for PBXProject "TLYShyNavBarSwiftDemo" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = E7ADE6011A99A83B00E8F95C;
productRefGroup = E7ADE60B1A99A83B00E8F95C /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
E7ADE6091A99A83B00E8F95C /* TLYShyNavBarSwiftDemo */,
E7ADE61E1A99A83B00E8F95C /* TLYShyNavBarSwiftDemoTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
E7ADE6081A99A83B00E8F95C /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E7ADE6151A99A83B00E8F95C /* Main.storyboard in Resources */,
E7ADE61A1A99A83B00E8F95C /* LaunchScreen.xib in Resources */,
E7ADE6171A99A83B00E8F95C /* Images.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E7ADE61D1A99A83B00E8F95C /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
E7ADE6061A99A83B00E8F95C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E7ADE63F1A99A84C00E8F95C /* TLYShyViewController.m in Sources */,
E7ADE63C1A99A84C00E8F95C /* UIViewController+BetterLayoutGuides.m in Sources */,
E7ADE6421A99AB5800E8F95C /* TableViewController.swift in Sources */,
E7ADE6101A99A83B00E8F95C /* AppDelegate.swift in Sources */,
E7ADE63D1A99A84C00E8F95C /* TLYDelegateProxy.m in Sources */,
E7ADE63E1A99A84C00E8F95C /* TLYShyNavBarManager.m in Sources */,
E7ADE63B1A99A84C00E8F95C /* NSObject+TLYSwizzlingHelpers.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E7ADE61B1A99A83B00E8F95C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E7ADE6261A99A83B00E8F95C /* TLYShyNavBarSwiftDemoTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
E7ADE6211A99A83B00E8F95C /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = E7ADE6091A99A83B00E8F95C /* TLYShyNavBarSwiftDemo */;
targetProxy = E7ADE6201A99A83B00E8F95C /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
E7ADE6131A99A83B00E8F95C /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
E7ADE6141A99A83B00E8F95C /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
E7ADE6181A99A83B00E8F95C /* LaunchScreen.xib */ = {
isa = PBXVariantGroup;
children = (
E7ADE6191A99A83B00E8F95C /* Base */,
);
name = LaunchScreen.xib;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
E7ADE6271A99A83B00E8F95C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
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;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
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_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
E7ADE6281A99A83B00E8F95C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
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;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
E7ADE62A1A99A83B00E8F95C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = TLYShyNavBarSwiftDemo/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Bridging-Header.h";
};
name = Debug;
};
E7ADE62B1A99A83B00E8F95C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = TLYShyNavBarSwiftDemo/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Bridging-Header.h";
};
name = Release;
};
E7ADE62D1A99A83B00E8F95C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = TLYShyNavBarSwiftDemoTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TLYShyNavBarSwiftDemo.app/TLYShyNavBarSwiftDemo";
};
name = Debug;
};
E7ADE62E1A99A83B00E8F95C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
INFOPLIST_FILE = TLYShyNavBarSwiftDemoTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TLYShyNavBarSwiftDemo.app/TLYShyNavBarSwiftDemo";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
E7ADE6051A99A83B00E8F95C /* Build configuration list for PBXProject "TLYShyNavBarSwiftDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E7ADE6271A99A83B00E8F95C /* Debug */,
E7ADE6281A99A83B00E8F95C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E7ADE6291A99A83B00E8F95C /* Build configuration list for PBXNativeTarget "TLYShyNavBarSwiftDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E7ADE62A1A99A83B00E8F95C /* Debug */,
E7ADE62B1A99A83B00E8F95C /* Release */,
);
defaultConfigurationIsVisible = 0;
};
E7ADE62C1A99A83B00E8F95C /* Build configuration list for PBXNativeTarget "TLYShyNavBarSwiftDemoTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E7ADE62D1A99A83B00E8F95C /* Debug */,
E7ADE62E1A99A83B00E8F95C /* Release */,
);
defaultConfigurationIsVisible = 0;
};
/* End XCConfigurationList section */
};
rootObject = E7ADE6021A99A83B00E8F95C /* Project object */;
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:TLYShyNavBarSwiftDemo.xcodeproj">
</FileRef>
</Workspace>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDESourceControlProjectFavoriteDictionaryKey</key>
<false/>
<key>IDESourceControlProjectIdentifier</key>
<string>72C64448-CAFE-4F5D-8307-0D51A162F41F</string>
<key>IDESourceControlProjectName</key>
<string>TLYShyNavBarSwiftDemo</string>
<key>IDESourceControlProjectOriginsDictionary</key>
<dict>
<key>58D55ECABAD5AAEB583BB3898420091CC2A418B2</key>
<string>github.com:TNuzzi/TLYShyNavBar.git</string>
</dict>
<key>IDESourceControlProjectPath</key>
<string>TLYShyNavBarSwiftDemo/TLYShyNavBarSwiftDemo.xcodeproj</string>
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
<dict>
<key>58D55ECABAD5AAEB583BB3898420091CC2A418B2</key>
<string>../../..</string>
</dict>
<key>IDESourceControlProjectURL</key>
<string>github.com:TNuzzi/TLYShyNavBar.git</string>
<key>IDESourceControlProjectVersion</key>
<integer>111</integer>
<key>IDESourceControlProjectWCCIdentifier</key>
<string>58D55ECABAD5AAEB583BB3898420091CC2A418B2</string>
<key>IDESourceControlProjectWCConfigurations</key>
<array>
<dict>
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>58D55ECABAD5AAEB583BB3898420091CC2A418B2</string>
<key>IDESourceControlWCCName</key>
<string>TLYShyNavBar</string>
</dict>
</array>
</dict>
</plist>

View File

@ -0,0 +1,23 @@
//
// AppDelegate.swift
// TLYShyNavBarSwiftDemo
//
// Created by Tony Nuzzi on 2/22/15.
// Copyright (c) 2015 Acktie, LLC. All rights reserved.
//
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
return true
}
}

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6214" systemVersion="14A314h" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6207"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2015 Acktie, LLC. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
<rect key="frame" x="20" y="439" width="441" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="TLYShyNavBarSwiftDemo" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<rect key="frame" x="20" y="140" width="441" height="43"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="548" y="455"/>
</view>
</objects>
</document>

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6254" systemVersion="14C109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="gcu-PF-Kdc">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
</dependencies>
<scenes>
<!--Demo-->
<scene sceneID="5MV-8R-1mp">
<objects>
<tableViewController id="u4f-jm-pLt" customClass="TableViewController" customModule="TLYShyNavBarSwiftDemo" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="yOB-Ib-nJT">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" id="rc9-p0-nKD">
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="rc9-p0-nKD" id="N7f-GN-2zs">
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Scroll" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lY6-Vg-XZm">
<rect key="frame" x="0.0" y="-21" width="42" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
<variation key="widthClass=compact" fixedFrame="YES">
<rect key="frame" x="8" y="8" width="44" height="21"/>
</variation>
</label>
</subviews>
<variation key="default">
<mask key="subviews">
<exclude reference="lY6-Vg-XZm"/>
</mask>
</variation>
<variation key="widthClass=compact">
<mask key="subviews">
<include reference="lY6-Vg-XZm"/>
</mask>
</variation>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="u4f-jm-pLt" id="0XH-xm-LBh"/>
<outlet property="delegate" destination="u4f-jm-pLt" id="B1g-9M-ck7"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Demo" id="mru-Ba-r9e"/>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="sOT-UF-3QF" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1765.5" y="967"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="VSn-a0-VnN">
<objects>
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="gcu-PF-Kdc" sceneMemberID="viewController">
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="mgn-kU-u8h">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
<connections>
<segue destination="u4f-jm-pLt" kind="relationship" relationship="rootViewController" id="ELf-J7-Ybx"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Frk-A2-IjM" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="847.5" y="967"/>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,38 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>com.acktie.test.swift.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,51 @@
//
// TableViewController.swift
// TLYShyNavBarSwiftDemo
//
// Created by Tony Nuzzi on 2/22/15.
// Copyright (c) 2015 Acktie, LLC. All rights reserved.
//
import UIKit
class TableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
/* In your UIViewController viewDidLoad or after creating the scroll view. */
self.shyNavBarManager.scrollView = self.tableView;
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return 50
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
return cell
}
}

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>com.acktie.test.swift.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

View File

@ -0,0 +1,36 @@
//
// TLYShyNavBarSwiftDemoTests.swift
// TLYShyNavBarSwiftDemoTests
//
// Created by Tony Nuzzi on 2/22/15.
// Copyright (c) 2015 Acktie, LLC. All rights reserved.
//
import UIKit
import XCTest
class TLYShyNavBarSwiftDemoTests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// This is an example of a functional test case.
XCTAssert(true, "Pass")
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measureBlock() {
// Put the code you want to measure the time of here.
}
}
}