├── LICENSE ├── LMPullToBounce.podspec ├── LMPullToBounce ├── BallView.h ├── BallView.m ├── BounceView.h ├── BounceView.m ├── Category │ ├── NSTimer+PullToBounce.h │ ├── NSTimer+PullToBounce.m │ ├── UIView+PullToBounce.h │ └── UIView+PullToBounce.m ├── CircleLayer.h ├── CircleLayer.m ├── LMPullToBounceWrapper.h ├── LMPullToBounceWrapper.m ├── SampleTableViewCell.h ├── SampleTableViewCell.m ├── SpinnerLayer.h ├── SpinnerLayer.m ├── WaveView.h └── WaveView.m ├── LMPullToBounceDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── LMPullToBounceDemo.xccheckout │ └── xcuserdata │ │ ├── luck-mac.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── luckymore.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── handwHandWinin.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ ├── LMPullToBounceDemo.xcscheme │ │ └── xcschememanagement.plist │ ├── luck-mac.xcuserdatad │ └── xcschemes │ │ ├── LMPullToBounceDemo.xcscheme │ │ └── xcschememanagement.plist │ └── luckymore.xcuserdatad │ └── xcschemes │ ├── LMPullToBounceDemo.xcscheme │ └── xcschememanagement.plist ├── LMPullToBounceDemo ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── DetailViewController.h ├── DetailViewController.m ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── SampleTableViewCell.h ├── SampleTableViewCell.m ├── ViewController.h ├── ViewController.m └── main.m ├── LMPullToBounceDemoTests ├── Info.plist └── LMPullToBounceDemoTests.m ├── LMPullToBounceTests ├── Info.plist └── WKPullToBounceTests.m └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 luckymore 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /LMPullToBounce.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "LMPullToBounce" 4 | s.version = "1.1.1" 5 | s.summary = "The Objective-C version of PullToBounce. Supports iOS 7.0+." 6 | s.description = <<-DESC 7 | An elegant “pull to refresh” animation, written in Objective-C, fix the crash when dealloc 8 | DESC 9 | s.homepage = "https://github.com/luckymore0520/LMPullToBounce" 10 | s.license = { :type => "MIT", :file => "LICENSE" } 11 | s.author = { "luckymore0520" => "njuluckwang@gmail.com" } 12 | s.social_media_url = "http://weibo.com/u/2274597140" 13 | s.platform = :ios, '7.0' 14 | 15 | s.source = { :git => "https://github.com/luckymore0520/LMPullToBounce.git", :tag => "1.1.1" } 16 | s.source_files = "LMPullToBounce", "LMPullToBounce/**/*.{h,m}" 17 | s.frameworks = 'Foundation', 'UIKit' 18 | 19 | 20 | end 21 | -------------------------------------------------------------------------------- /LMPullToBounce/BallView.h: -------------------------------------------------------------------------------- 1 | // 2 | // BallView.h 3 | // 4 | // 5 | // Created by luck-mac on 15/8/18. 6 | // 7 | // 8 | 9 | #import 10 | #import "CircleLayer.h" 11 | 12 | @interface BallView : UIView 13 | - (instancetype) initWithFrame:(CGRect) frame 14 | circleSize:(CGFloat)circleSize 15 | timingFunc:(CAMediaTimingFunction *)timeFunction 16 | moveUpDuration:(CFTimeInterval)moveUpDuration 17 | moveUpDist:(CGFloat)moveUpDist 18 | color:(UIColor *)color; 19 | - (void) startAnimation; 20 | - (void) endAnimationWithCompletion:(AnimationCompletion)completion; 21 | @end 22 | 23 | -------------------------------------------------------------------------------- /LMPullToBounce/BallView.m: -------------------------------------------------------------------------------- 1 | // 2 | // BallView.m 3 | // 4 | // 5 | // Created by luck-mac on 15/8/18. 6 | // 7 | // 8 | 9 | #import "BallView.h" 10 | #import "UIView+PullToBounce.h" 11 | 12 | @interface BallView() 13 | @property (nonatomic, strong) CircleLayer *circleLayer; 14 | @end 15 | 16 | @implementation BallView 17 | - (instancetype) initWithFrame:(CGRect) frame 18 | circleSize:(CGFloat)circleSize 19 | timingFunc:(CAMediaTimingFunction *)timeFunction 20 | moveUpDuration:(CFTimeInterval)moveUpDuration 21 | moveUpDist:(CGFloat)moveUpDist 22 | color:(UIColor *)color{ 23 | self = [self initWithFrame:frame]; 24 | if (self) { 25 | UIView *circleMoveView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, moveUpDist, moveUpDist)]; 26 | circleMoveView.center = CGPointMake(self.width / 2, self.height + circleSize / 2); 27 | [self addSubview:circleMoveView]; 28 | self.circleLayer = [[CircleLayer alloc] initWithSize:circleSize moveUpDist:moveUpDist superViewFrame:circleMoveView.frame color:color timeFunc:timeFunction upDuration:moveUpDuration]; 29 | [circleMoveView.layer addSublayer:self.circleLayer]; 30 | } 31 | return self; 32 | } 33 | 34 | - (void) startAnimation { 35 | [self.circleLayer startAnimation]; 36 | } 37 | 38 | - (void) endAnimationWithCompletion:(AnimationCompletion)completion { 39 | [self.circleLayer endAnimation:completion]; 40 | } 41 | 42 | @end 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /LMPullToBounce/BounceView.h: -------------------------------------------------------------------------------- 1 | // 2 | // BounceView.h 3 | // 4 | // 5 | // Created by luck-mac on 15/8/18. 6 | // 7 | // 8 | 9 | #import 10 | #import "BallView.h" 11 | #import "WaveView.h" 12 | 13 | @interface BounceView : UIView 14 | - (instancetype)initWithFrame:(CGRect)frame 15 | bounceDuration:(CFTimeInterval)duration 16 | ballSize:(CGFloat)ballSize 17 | ballMovingTimingFunc:(CAMediaTimingFunction *)ballMovingTimingFunc moveUpDuration:(CFTimeInterval)moveUpDuration 18 | moveUpDist:(CGFloat)moveUpDist 19 | color:(UIColor *)color; 20 | 21 | - (void)wave:(CGFloat)y; 22 | - (void)didRelease:(CGFloat)y; 23 | - (void)endingAnimation:(AnimationCompletion)completion; 24 | @end 25 | -------------------------------------------------------------------------------- /LMPullToBounce/BounceView.m: -------------------------------------------------------------------------------- 1 | // 2 | // BounceView.m 3 | // 4 | // 5 | // Created by luck-mac on 15/8/18. 6 | // 7 | // 8 | 9 | #import "BounceView.h" 10 | #import "NSTimer+PullToBounce.h" 11 | #import "UIView+PullToBounce.h" 12 | 13 | @interface BounceView() 14 | @property (nonatomic, strong)BallView *ballView; 15 | @property (nonatomic, strong)WaveView *waveView; 16 | @end 17 | @implementation BounceView 18 | 19 | - (instancetype)initWithFrame:(CGRect)frame 20 | bounceDuration:(CFTimeInterval)duration 21 | ballSize:(CGFloat)ballSize 22 | ballMovingTimingFunc:(CAMediaTimingFunction *)ballMovingTimingFunc moveUpDuration:(CFTimeInterval)moveUpDuration 23 | moveUpDist:(CGFloat)moveUpDist 24 | color:(UIColor *)color { 25 | self = [self initWithFrame:frame]; 26 | if (self) { 27 | if (color == nil) { 28 | color = [UIColor whiteColor]; 29 | } 30 | CGFloat ballViewHeight = 100.0; 31 | 32 | self.ballView = [[BallView alloc] initWithFrame:CGRectMake(0, -(ballViewHeight + 1), self.width, ballViewHeight) 33 | circleSize:ballSize 34 | timingFunc:ballMovingTimingFunc 35 | moveUpDuration:moveUpDuration 36 | moveUpDist:moveUpDist 37 | color:color]; 38 | self.waveView = [[WaveView alloc] initWithFrame:CGRectMake(0, 0, self.ballView.width, self.height) 39 | bounceDuration:duration 40 | color:color]; 41 | self.ballView.hidden = YES; 42 | [self addSubview:self.ballView]; 43 | [self addSubview:self.waveView]; 44 | WS(weakSelf); 45 | [self.waveView setDidEndPull:^(){ 46 | [NSTimer schedule:0.2 handler:^(CFRunLoopTimerRef timer) { 47 | weakSelf.ballView.hidden = NO; 48 | [weakSelf.ballView startAnimation]; 49 | }]; 50 | }]; 51 | } 52 | return self; 53 | } 54 | 55 | #pragma mark - Public 56 | - (void)endingAnimation:(AnimationCompletion)completion { 57 | WS(weakSelf); 58 | [self.ballView endAnimationWithCompletion:^{ 59 | weakSelf.ballView.hidden = YES; 60 | if (completion) { 61 | completion(); 62 | } 63 | }]; 64 | } 65 | 66 | - (void)wave:(CGFloat)y { 67 | [self.waveView wave:y]; 68 | } 69 | 70 | - (void)didRelease:(CGFloat)y { 71 | [self.waveView didReleaseWithAmountX:0 amountY:y]; 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /LMPullToBounce/Category/NSTimer+PullToBounce.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSTimer+PullToBounce.h 3 | // 4 | // 5 | // Created by luck-mac on 15/8/18. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface NSTimer (PullToBounce) 12 | + (CFRunLoopTimerRef)schedule:(NSTimeInterval)delay handler:(void (^)(CFRunLoopTimerRef))handler; 13 | @end 14 | -------------------------------------------------------------------------------- /LMPullToBounce/Category/NSTimer+PullToBounce.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSTimer+PullToBounce.m 3 | // 4 | // 5 | // Created by luck-mac on 15/8/18. 6 | // 7 | // 8 | 9 | #import "NSTimer+PullToBounce.h" 10 | 11 | @implementation NSTimer (PullToBounce) 12 | + (CFRunLoopTimerRef)schedule:(NSTimeInterval)delay handler:(void (^)(CFRunLoopTimerRef))handler { 13 | NSTimeInterval fireDate = CFAbsoluteTimeGetCurrent() + delay; 14 | CFRunLoopTimerRef timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, 0, 0, 0, handler); 15 | CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopCommonModes); 16 | return timer; 17 | } 18 | @end 19 | -------------------------------------------------------------------------------- /LMPullToBounce/Category/UIView+PullToBounce.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+PullToBounce.h 3 | // 4 | // 5 | // Created by luck-mac on 15/8/18. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface UIView (PullToBounce) 12 | @property (nonatomic, assign) CGFloat width; 13 | @property (nonatomic, assign) CGFloat height; 14 | @property (nonatomic, assign) CGFloat top; 15 | @property (nonatomic, assign) CGFloat bottom; 16 | @property (nonatomic, assign) CGFloat left; 17 | @property (nonatomic, assign) CGFloat right; 18 | @end 19 | -------------------------------------------------------------------------------- /LMPullToBounce/Category/UIView+PullToBounce.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+PullToBounce.m 3 | // 4 | // 5 | // Created by luck-mac on 15/8/18. 6 | // 7 | // 8 | 9 | #import "UIView+PullToBounce.h" 10 | 11 | @implementation UIView (PullToBounce) 12 | - (CGFloat)width { 13 | return self.frame.size.width; 14 | } 15 | 16 | - (CGFloat)height { 17 | return self.frame.size.height; 18 | } 19 | 20 | - (void)setWidth:(CGFloat)width { 21 | CGRect frame = self.frame; 22 | frame.size.width = width; 23 | self.frame = frame; 24 | } 25 | 26 | - (void)setHeight:(CGFloat)height { 27 | CGRect frame = self.frame; 28 | frame.size.height = height; 29 | self.frame = frame; 30 | } 31 | 32 | - (void)setTop:(CGFloat)top 33 | { 34 | CGRect frame = self.frame; 35 | frame.origin.y = top; 36 | self.frame = frame; 37 | } 38 | 39 | - (CGFloat)top 40 | { 41 | return self.frame.origin.y; 42 | } 43 | 44 | 45 | - (void)setBottom:(CGFloat)bottom 46 | { 47 | CGRect frame = self.frame; 48 | frame.origin.y = bottom - frame.size.height; 49 | self.frame = frame; 50 | } 51 | 52 | 53 | - (CGFloat)bottom { 54 | return self.frame.origin.y + self.frame.size.height; 55 | } 56 | 57 | 58 | - (void)setLeft:(CGFloat)left 59 | { 60 | CGRect frame = self.frame; 61 | frame.origin.x = left; 62 | self.frame = frame; 63 | } 64 | 65 | 66 | - (CGFloat)left 67 | { 68 | return self.frame.origin.x; 69 | } 70 | 71 | 72 | - (void)setRight:(CGFloat)right 73 | { 74 | CGRect frame = self.frame; 75 | frame.origin.x = right - frame.size.width; 76 | self.frame = frame; 77 | } 78 | 79 | 80 | - (CGFloat)right 81 | { 82 | return self.frame.origin.x + self.frame.size.width; 83 | } 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /LMPullToBounce/CircleLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // CircleLayer.h 3 | // LMPullToBounceDemo 4 | // 5 | // Created by WangKun on 16/9/3. 6 | // Copyright © 2016年 com.nju.luckymore. All rights reserved. 7 | // 8 | 9 | #import "SpinnerLayer.h" 10 | 11 | @interface CircleLayer :CAShapeLayer 12 | @property (nonatomic, assign) CGFloat moveUpDist; 13 | @property (nonatomic, strong) SpinnerLayer *spiner; 14 | @property (nonatomic, strong) AnimationCompletion didEndAnimation; 15 | - (instancetype)initWithSize:(CGFloat)size 16 | moveUpDist:(CGFloat)moveUpDist 17 | superViewFrame:(CGRect)superViewFrame 18 | color:(UIColor *)color 19 | timeFunc:(CAMediaTimingFunction *)timeFunc 20 | upDuration:(CGFloat)upDuration; 21 | - (void)startAnimation; 22 | - (void)endAnimation:(AnimationCompletion)completion; 23 | @end -------------------------------------------------------------------------------- /LMPullToBounce/CircleLayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // CircleLayer.m 3 | // LMPullToBounceDemo 4 | // 5 | // Created by WangKun on 16/9/3. 6 | // Copyright © 2016年 com.nju.luckymore. All rights reserved. 7 | // 8 | 9 | #import "CircleLayer.h" 10 | #import "NSTimer+PullToBounce.h" 11 | 12 | @interface CircleLayer() 13 | @property (nonatomic, strong) CAMediaTimingFunction *timeFunc; 14 | @property (nonatomic, assign) CGFloat upDuration; 15 | @end 16 | @implementation CircleLayer 17 | - (instancetype)initWithSize:(CGFloat)size 18 | moveUpDist:(CGFloat)moveUpDist 19 | superViewFrame:(CGRect)superViewFrame 20 | color:(UIColor *)color 21 | timeFunc:(CAMediaTimingFunction *)timeFunc 22 | upDuration:(CGFloat)upDuration{ 23 | self = [self init]; 24 | if (self) { 25 | self.timeFunc = timeFunc; 26 | self.upDuration = upDuration; 27 | self.moveUpDist = moveUpDist; 28 | self.frame = CGRectMake(0, 0, superViewFrame.size.width, superViewFrame.size.height); 29 | self.spiner = [[SpinnerLayer alloc] initWithSuperLayoutFrame:self.frame ballSize:size color:color]; 30 | [self addSublayer:self.spiner]; 31 | CGPoint center = CGPointMake(superViewFrame.size.width / 2, superViewFrame.size.height / 2); 32 | CGFloat radius = size / 2; 33 | CGFloat startAngle = 0 - M_PI_2; 34 | CGFloat endAngle = M_PI * 2 - M_PI_2; 35 | self.path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES].CGPath; 36 | self.fillColor = color.CGColor; 37 | self.strokeColor = self.fillColor; 38 | self.lineWidth = 0; 39 | self.strokeEnd = 1; 40 | } 41 | return self; 42 | } 43 | 44 | #pragma mark - Public 45 | - (void)startAnimation { 46 | [self moveUp:self.moveUpDist]; 47 | WS(weakSelf); 48 | [NSTimer schedule:self.upDuration handler:^(CFRunLoopTimerRef timer) { 49 | [weakSelf.spiner animation]; 50 | }]; 51 | } 52 | 53 | - (void)endAnimation:(AnimationCompletion)completion{ 54 | [self.spiner stopAnimation]; 55 | [self moveDown:self.moveUpDist]; 56 | self.didEndAnimation = completion; 57 | } 58 | 59 | #pragma mark - Private 60 | - (void)moveUp:(CGFloat)distance { 61 | CABasicAnimation *move = [CABasicAnimation animationWithKeyPath:@"position"]; 62 | move.fromValue = [NSValue valueWithCGPoint:self.position]; 63 | move.toValue = [NSValue valueWithCGPoint:CGPointMake(self.position.x, self.position.y - distance)]; 64 | move.duration = self.upDuration; 65 | move.timingFunction = self.timeFunc; 66 | move.fillMode = kCAFillModeForwards; 67 | move.removedOnCompletion = NO; 68 | [self addAnimation:move forKey:move.keyPath]; 69 | } 70 | 71 | - (void)moveDown:(CGFloat)distance { 72 | CABasicAnimation *move = [CABasicAnimation animationWithKeyPath:@"position"]; 73 | move.toValue = [NSValue valueWithCGPoint:self.position]; 74 | move.fromValue = [NSValue valueWithCGPoint:CGPointMake(self.position.x, self.position.y - distance)]; 75 | move.duration = self.upDuration; 76 | move.timingFunction = self.timeFunc; 77 | move.fillMode = kCAFillModeForwards; 78 | move.removedOnCompletion = NO; 79 | move.delegate = self; 80 | [self addAnimation:move forKey:move.keyPath]; 81 | } 82 | 83 | #pragma mark - CAAnimationDelegate 84 | - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { 85 | if (self.didEndAnimation) { 86 | self.didEndAnimation(); 87 | } 88 | } 89 | 90 | @end 91 | 92 | -------------------------------------------------------------------------------- /LMPullToBounce/LMPullToBounceWrapper.h: -------------------------------------------------------------------------------- 1 | // 2 | // WKPullToBounceWrapper.h 3 | // 4 | // 5 | // Created by luck-mac on 15/8/19. 6 | // 7 | // 8 | 9 | #import 10 | 11 | typedef void (^DidPullToRefresh)(); 12 | @interface LMPullToBounceWrapper : UIView 13 | @property (nonatomic, strong) DidPullToRefresh didPullTorefresh; 14 | - (instancetype) initWithScrollView:(UIScrollView *)scrollView 15 | bounceDuration:(CFTimeInterval)bounceDuration 16 | ballSize:(CGFloat)ballSize 17 | ballMoveTimeFunc:(CAMediaTimingFunction *)ballMoveTimeFunc 18 | moveUpDuration:(CFTimeInterval)moveUpDuration 19 | pullDistance:(CGFloat)pullDistance 20 | bendDistance:(CGFloat)bendDistance 21 | didPullToRefresh:(DidPullToRefresh)didPullToRefresh; 22 | - (instancetype) initWithScrollView:(UIScrollView *)scrollView; 23 | - (void)stopLoadingAnimation; 24 | @end 25 | -------------------------------------------------------------------------------- /LMPullToBounce/LMPullToBounceWrapper.m: -------------------------------------------------------------------------------- 1 | // 2 | // WKPullToBounceWrapper.m 3 | // 4 | // 5 | // Created by luck-mac on 15/8/19. 6 | // 7 | // 8 | 9 | #import "LMPullToBounceWrapper.h" 10 | #import "BounceView.h" 11 | #import "UIView+PullToBounce.h" 12 | 13 | #define CONTENTOFFSET_KEYPATH @"contentOffset" 14 | 15 | @interface LMPullToBounceWrapper() 16 | @property (nonatomic, assign)CGFloat pullDist; 17 | @property (nonatomic, assign)CGFloat bendDist; 18 | @property (nonatomic, readonly) CGFloat stopPos; 19 | @property (nonatomic, strong) BounceView *bounceView; 20 | @property (nonatomic, weak) UIScrollView *scrollView; 21 | @end 22 | 23 | @implementation LMPullToBounceWrapper 24 | - (instancetype)initWithScrollView:(UIScrollView *)scrollView { 25 | return [self initWithScrollView:scrollView 26 | bounceDuration:0.8 27 | ballSize:36 28 | ballMoveTimeFunc:[CAMediaTimingFunction functionWithControlPoints:0.49 :0.13 :0.29 :1.61] 29 | moveUpDuration:0.25 30 | pullDistance:96 31 | bendDistance:40 32 | didPullToRefresh:nil]; 33 | } 34 | 35 | - (instancetype)initWithScrollView:(UIScrollView *)scrollView 36 | bounceDuration:(CFTimeInterval)bounceDuration 37 | ballSize:(CGFloat)ballSize 38 | ballMoveTimeFunc:(CAMediaTimingFunction *)ballMoveTimeFunc 39 | moveUpDuration:(CFTimeInterval)moveUpDuration 40 | pullDistance:(CGFloat)pullDistance 41 | bendDistance:(CGFloat)bendDistance 42 | didPullToRefresh:(DidPullToRefresh)didPullToRefresh { 43 | self = [self initWithFrame:scrollView.frame]; 44 | if (self) { 45 | self.pullDist = pullDistance; 46 | self.bendDist = bendDistance; 47 | self.didPullTorefresh = didPullToRefresh; 48 | 49 | CGFloat moveUpDist = pullDistance / 2 + ballSize / 2; 50 | 51 | self.bounceView = [[BounceView alloc] initWithFrame:self.frame 52 | bounceDuration:bounceDuration 53 | ballSize:ballSize 54 | ballMovingTimingFunc:ballMoveTimeFunc 55 | moveUpDuration:moveUpDuration 56 | moveUpDist:moveUpDist 57 | color:self.scrollView.backgroundColor]; 58 | [self addSubview:self.bounceView]; 59 | self.scrollView = scrollView; 60 | scrollView.backgroundColor = [UIColor clearColor]; 61 | [self addSubview:scrollView]; 62 | [scrollView addObserver:self forKeyPath:CONTENTOFFSET_KEYPATH options:NSKeyValueObservingOptionInitial context:nil]; 63 | } 64 | return self; 65 | } 66 | 67 | - (void)dealloc { 68 | [self.scrollView removeObserver:self forKeyPath:CONTENTOFFSET_KEYPATH]; 69 | } 70 | 71 | #pragma mark - Public 72 | - (void)stopLoadingAnimation { 73 | WS(weakSelf); 74 | [self.bounceView endingAnimation:^{ 75 | [weakSelf.scrollView setContentOffset:CGPointZero animated:YES]; 76 | weakSelf.scrollView.scrollEnabled = YES; 77 | }]; 78 | } 79 | 80 | #pragma mark - Getter 81 | - (CGFloat)stopPos { 82 | return self.pullDist + self.bendDist; 83 | } 84 | 85 | 86 | #pragma mark - KVO 87 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 88 | if ([keyPath isEqualToString:CONTENTOFFSET_KEYPATH]) { 89 | if ([object isKindOfClass:[UIScrollView class]]) { 90 | [self scrollViewDidScroll]; 91 | } 92 | } 93 | } 94 | 95 | - (void)scrollViewDidScroll { 96 | UIScrollView *scrollView = self.scrollView; 97 | if (scrollView.contentOffset.y < 0) { 98 | CGFloat y = - scrollView.contentOffset.y; 99 | if (y < self.pullDist) { 100 | self.bounceView.top = y; 101 | [self.bounceView wave:0]; 102 | self.scrollView.alpha = (self.pullDist - y)/self.pullDist; 103 | } else if ( y < self.stopPos) { 104 | [self.bounceView wave: y-self.pullDist]; 105 | self.scrollView.alpha = 0; 106 | } else if (y > self.stopPos) { 107 | self.scrollView.scrollEnabled = NO; 108 | [self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, -[self stopPos]) animated:NO]; 109 | self.bounceView.top = self.pullDist; 110 | [self.bounceView wave:(self.stopPos - self.pullDist)]; 111 | [self.bounceView didRelease:(self.stopPos - self.pullDist)]; 112 | if (self.didPullTorefresh) { 113 | self.didPullTorefresh(); 114 | } 115 | self.scrollView.alpha = 0; 116 | } 117 | } else { 118 | CGRect frame = self.bounceView.frame; 119 | frame.origin.y = 0; 120 | self.bounceView.frame = frame; 121 | self.scrollView.alpha = 1; 122 | } 123 | } 124 | 125 | 126 | 127 | @end 128 | -------------------------------------------------------------------------------- /LMPullToBounce/SampleTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // SampleTableViewCell.h 3 | // 4 | // 5 | // Created by luck-mac on 15/8/19. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface SampleTableViewCell : UITableViewCell 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /LMPullToBounce/SampleTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // SampleTableViewCell.m 3 | // 4 | // 5 | // Created by luck-mac on 15/8/19. 6 | // 7 | // 8 | 9 | #import "SampleTableViewCell.h" 10 | #import "UIView+PullToBounce.h" 11 | 12 | @implementation SampleTableViewCell 13 | 14 | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 15 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 16 | if (self) { 17 | UIView *iconMock = [[UIView alloc] initWithFrame:CGRectMake(16, 16, 60, 60)]; 18 | iconMock.layer.cornerRadius = 10; 19 | [iconMock setClipsToBounds:YES]; 20 | iconMock.backgroundColor = [UIColor colorWithRed:0.700062 green:0.817345 blue:0.972549 alpha:1];; 21 | [self addSubview:iconMock]; 22 | CGFloat lineLeft = iconMock.right + 16; 23 | CGFloat lineMargin = 12; 24 | 25 | CGRect lineFrame1 = CGRectMake(lineLeft, lineMargin + 12 , 100, 6); 26 | UIView *line1 = [self addLine:lineFrame1]; 27 | CGRect lineFrame2 = CGRectMake(lineLeft, line1.bottom + lineMargin, 160, 5); 28 | UIView *line2 = [self addLine:lineFrame2]; 29 | CGRect lineFrame3 = CGRectMake(lineLeft, line2.bottom + lineMargin, 180, 5); 30 | [self addLine:lineFrame3]; 31 | 32 | UIView *seperator = [[UIView alloc] initWithFrame:CGRectMake(0, 91, self.width, 1)]; 33 | seperator.backgroundColor = [[UIColor grayColor] colorWithAlphaComponent:0.2]; 34 | [self addSubview:seperator]; 35 | } 36 | return self; 37 | } 38 | 39 | - (UIView *)addLine:(CGRect)lineFrame { 40 | UIView *line = [[UIView alloc] initWithFrame:lineFrame]; 41 | line.layer.cornerRadius = line.height; 42 | line.backgroundColor = [UIColor colorWithRed:0.700062 green:0.817345 blue:0.972549 alpha:1]; 43 | [self addSubview:line]; 44 | return line; 45 | } 46 | 47 | - (void)awakeFromNib { 48 | // Initialization code 49 | } 50 | 51 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 52 | [super setSelected:selected animated:animated]; 53 | 54 | // Configure the view for the selected state 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /LMPullToBounce/SpinnerLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // SpinnerLayer.h 3 | // LMPullToBounceDemo 4 | // 5 | // Created by WangKun on 16/9/3. 6 | // Copyright © 2016年 com.nju.luckymore. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | #define WS(weakSelf) __weak __typeof(&*self)weakSelf = self; 13 | typedef void (^AnimationCompletion)(); 14 | @interface SpinnerLayer :CAShapeLayer 15 | - (void)animation; 16 | - (void)stopAnimation; 17 | - (instancetype)initWithSuperLayoutFrame:(CGRect)superLayerFrame 18 | ballSize:(CGFloat)ballSize 19 | color:(UIColor *)color; 20 | @end 21 | -------------------------------------------------------------------------------- /LMPullToBounce/SpinnerLayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // SpinnerLayer.m 3 | // LMPullToBounceDemo 4 | // 5 | // Created by WangKun on 16/9/3. 6 | // Copyright © 2016年 com.nju.luckymore. All rights reserved. 7 | // 8 | 9 | #import "SpinnerLayer.h" 10 | @implementation SpinnerLayer 11 | 12 | - (instancetype)initWithSuperLayoutFrame:(CGRect)superLayerFrame 13 | ballSize:(CGFloat)ballSize 14 | color:(UIColor *)color { 15 | self = [super init]; 16 | if (self) { 17 | self.frame = CGRectMake(0, 0, superLayerFrame.size.height, superLayerFrame.size.height); 18 | CGPoint center = CGPointMake(superLayerFrame.size.width / 2, superLayerFrame.origin.y + superLayerFrame.size.height / 2); 19 | const CGFloat startAngle = - M_PI_2; 20 | const CGFloat endAngle = (M_PI * 2 - M_PI_2) + M_PI / 8; 21 | CGFloat radius = ballSize / 2 * 1.2; 22 | self.path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES].CGPath; 23 | self.fillColor = nil; 24 | self.strokeColor = color.CGColor; 25 | self.lineWidth = 2.0; 26 | self.lineCap = kCALineCapRound; 27 | self.strokeStart = 0; 28 | self.strokeEnd = 0; 29 | self.hidden = YES; 30 | } 31 | return self; 32 | } 33 | 34 | #pragma mark - Public 35 | - (void)animation { 36 | self.hidden = NO; 37 | CABasicAnimation *rotate = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; 38 | rotate.fromValue = @(0); 39 | rotate.toValue = @(M_PI * 2); 40 | rotate.duration = 1; 41 | rotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 42 | rotate.repeatCount = HUGE; 43 | rotate.fillMode = kCAFillModeForwards; 44 | rotate.removedOnCompletion = NO; 45 | [self addAnimation:rotate forKey:rotate.keyPath]; 46 | [self strokeEndAnimation]; 47 | } 48 | 49 | - (void)stopAnimation { 50 | [self setHidden:YES]; 51 | [self removeAllAnimations]; 52 | } 53 | 54 | #pragma mark - Private 55 | - (void)strokeEndAnimation { 56 | CABasicAnimation *endPoint = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; 57 | endPoint.fromValue = @(0); 58 | endPoint.toValue = @(1.0); 59 | endPoint.duration = 0.8; 60 | endPoint.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; 61 | endPoint.repeatCount = 1; 62 | endPoint.fillMode = kCAFillModeForwards; 63 | endPoint.removedOnCompletion = NO; 64 | endPoint.delegate = self; 65 | [self addAnimation:endPoint forKey:endPoint.keyPath]; 66 | } 67 | 68 | 69 | - (void)strokeStartAnimation { 70 | CABasicAnimation *startPoint = [CABasicAnimation animationWithKeyPath:@"strokeStart"]; 71 | startPoint.fromValue = @(0); 72 | startPoint.toValue = @(1.0); 73 | startPoint.duration = 0.8; 74 | startPoint.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; 75 | startPoint.repeatCount = 1; 76 | startPoint.delegate = self; 77 | [self addAnimation:startPoint forKey:startPoint.keyPath]; 78 | } 79 | 80 | #pragma mark - CAAnimationDelegate 81 | - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { 82 | if (!self.hidden) { 83 | CABasicAnimation *animation = (CABasicAnimation *)anim; 84 | if ([animation.keyPath isEqualToString:@"strokeStart"]) { 85 | [self strokeEndAnimation]; 86 | } else if ([animation.keyPath isEqualToString:@"strokeEnd"]) { 87 | [self strokeStartAnimation]; 88 | } 89 | } 90 | } 91 | @end 92 | -------------------------------------------------------------------------------- /LMPullToBounce/WaveView.h: -------------------------------------------------------------------------------- 1 | // 2 | // WaveView.h 3 | // 4 | // 5 | // Created by luck-mac on 15/8/18. 6 | // 7 | // 8 | 9 | #import 10 | 11 | typedef void (^EndPullHandler)(); 12 | @interface WaveView : UIView 13 | @property (nonatomic, strong) EndPullHandler didEndPull; 14 | - (instancetype) initWithFrame:(CGRect)frame 15 | bounceDuration:(CFTimeInterval) duration 16 | color:(UIColor *)color; 17 | - (void)wave:(CGFloat)y; 18 | - (void)didReleaseWithAmountX:(CGFloat)amountX amountY:(CGFloat)amountY; 19 | @end 20 | -------------------------------------------------------------------------------- /LMPullToBounce/WaveView.m: -------------------------------------------------------------------------------- 1 | // 2 | // WaveView.m 3 | // 4 | // 5 | // Created by luck-mac on 15/8/18. 6 | // 7 | // 8 | 9 | #import "WaveView.h" 10 | #import "UIView+PullToBounce.h" 11 | #define WS(weakSelf) __weak __typeof(&*self)weakSelf = self; 12 | 13 | @interface WaveView() 14 | @property (nonatomic, assign) CFTimeInterval bounceDuration; 15 | @property (nonatomic, strong) CAShapeLayer *waveLayer; 16 | @end 17 | @implementation WaveView 18 | 19 | - (instancetype) initWithFrame:(CGRect)frame 20 | bounceDuration:(CFTimeInterval) duration 21 | color:(UIColor *)color { 22 | self = [self initWithFrame:frame]; 23 | if (self) { 24 | self.bounceDuration = duration; 25 | self.waveLayer = [[CAShapeLayer alloc] initWithLayer:self.layer]; 26 | self.waveLayer.lineWidth = 0; 27 | self.waveLayer.path = [self wavePathWithAmountX:0 amountY:0]; 28 | self.waveLayer.strokeColor = color.CGColor; 29 | self.waveLayer.fillColor = color.CGColor; 30 | [self.layer addSublayer:self.waveLayer]; 31 | } 32 | return self; 33 | } 34 | 35 | #pragma mark - Public 36 | - (void)wave:(CGFloat)y { 37 | self.waveLayer.path = [self wavePathWithAmountX:0 amountY:y]; 38 | } 39 | 40 | - (void)didReleaseWithAmountX:(CGFloat)amountX amountY:(CGFloat)amountY { 41 | [self boundAnimationWithPositionX:amountX positionY:amountY]; 42 | if (self.didEndPull) { 43 | self.didEndPull(); 44 | } 45 | } 46 | 47 | #pragma mark - CAAnimationDelegate 48 | - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { 49 | self.waveLayer.path = [self wavePathWithAmountX:0 amountY:0]; 50 | } 51 | 52 | #pragma mark - Private 53 | - (void)boundAnimationWithPositionX:(CGFloat) positionX positionY:(CGFloat)positionY { 54 | self.waveLayer.path = [self wavePathWithAmountX:0 amountY:0]; 55 | CAKeyframeAnimation *bounce = [CAKeyframeAnimation animationWithKeyPath:@"path"]; 56 | bounce.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; 57 | NSArray *values = @[ 58 | (__bridge id)[self wavePathWithAmountX:positionX amountY:positionY], 59 | (__bridge id)[self wavePathWithAmountX:-(positionX * 0.7) amountY:-(positionY * 0.7)], 60 | (__bridge id)[self wavePathWithAmountX:(positionX * 0.4) amountY:(positionY * 0.4)], 61 | (__bridge id)[self wavePathWithAmountX:-(positionX * 0.3) amountY:-(positionY * 0.3)], 62 | (__bridge id)[self wavePathWithAmountX:(positionX * 0.15) amountY:(positionY * 0.15)], 63 | (__bridge id)[self wavePathWithAmountX:0 amountY:0] 64 | ]; 65 | bounce.values = values; 66 | bounce.duration = self.bounceDuration; 67 | bounce.removedOnCompletion = YES; 68 | bounce.fillMode = kCAFillModeForwards; 69 | bounce.delegate = self; 70 | [self.waveLayer addAnimation:bounce forKey:@"return"]; 71 | } 72 | 73 | - (CGPathRef)wavePathWithAmountX:(CGFloat)amountX amountY:(CGFloat)amountY { 74 | CGFloat width = self.width; 75 | CGFloat height = self.height; 76 | CGFloat centerY = 0; 77 | CGFloat bottomY = height; 78 | CGPoint topLeftPoint = CGPointMake(0, centerY); 79 | CGPoint topMidPoint = CGPointMake(width / 2 + amountX, centerY + amountY); 80 | CGPoint topRightPoint = CGPointMake(width, centerY); 81 | CGPoint bottomLeftPoint = CGPointMake(0, bottomY); 82 | CGPoint bottomRightPoint = CGPointMake(width, bottomY); 83 | UIBezierPath *bezierPath = [[UIBezierPath alloc] init]; 84 | [bezierPath moveToPoint:bottomLeftPoint]; 85 | [bezierPath addLineToPoint:topLeftPoint]; 86 | [bezierPath addQuadCurveToPoint:topRightPoint controlPoint:topMidPoint]; 87 | [bezierPath addLineToPoint:bottomRightPoint]; 88 | return bezierPath.CGPath; 89 | } 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /LMPullToBounceDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1207D31B1D7ABC0100DFF2DB /* CircleLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1207D31A1D7ABC0100DFF2DB /* CircleLayer.m */; }; 11 | 1207D31E1D7ABC5300DFF2DB /* SpinnerLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1207D31D1D7ABC5300DFF2DB /* SpinnerLayer.m */; }; 12 | 4860F7FB1BA83FBC008BEF70 /* DetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4860F7FA1BA83FBC008BEF70 /* DetailViewController.m */; }; 13 | 7DF17C0D1B84B54D00DD3F33 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF17C0C1B84B54D00DD3F33 /* main.m */; }; 14 | 7DF17C101B84B54D00DD3F33 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF17C0F1B84B54D00DD3F33 /* AppDelegate.m */; }; 15 | 7DF17C131B84B54D00DD3F33 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF17C121B84B54D00DD3F33 /* ViewController.m */; }; 16 | 7DF17C161B84B54D00DD3F33 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7DF17C141B84B54D00DD3F33 /* Main.storyboard */; }; 17 | 7DF17C181B84B54D00DD3F33 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7DF17C171B84B54D00DD3F33 /* Images.xcassets */; }; 18 | 7DF17C1B1B84B54D00DD3F33 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7DF17C191B84B54D00DD3F33 /* LaunchScreen.xib */; }; 19 | 7DF17C271B84B54D00DD3F33 /* LMPullToBounceDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF17C261B84B54D00DD3F33 /* LMPullToBounceDemoTests.m */; }; 20 | 7DF17C571B84B5DD00DD3F33 /* BallView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF17C491B84B5DD00DD3F33 /* BallView.m */; }; 21 | 7DF17C581B84B5DD00DD3F33 /* BounceView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF17C4B1B84B5DD00DD3F33 /* BounceView.m */; }; 22 | 7DF17C591B84B5DD00DD3F33 /* NSTimer+PullToBounce.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF17C4E1B84B5DD00DD3F33 /* NSTimer+PullToBounce.m */; }; 23 | 7DF17C5A1B84B5DD00DD3F33 /* UIView+PullToBounce.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF17C501B84B5DD00DD3F33 /* UIView+PullToBounce.m */; }; 24 | 7DF17C5B1B84B5DD00DD3F33 /* LMPullToBounceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF17C521B84B5DD00DD3F33 /* LMPullToBounceWrapper.m */; }; 25 | 7DF17C5C1B84B5DD00DD3F33 /* SampleTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF17C541B84B5DD00DD3F33 /* SampleTableViewCell.m */; }; 26 | 7DF17C5D1B84B5DD00DD3F33 /* WaveView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF17C561B84B5DD00DD3F33 /* WaveView.m */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXContainerItemProxy section */ 30 | 7DF17C211B84B54D00DD3F33 /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = 7DF17BFF1B84B54D00DD3F33 /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = 7DF17C061B84B54D00DD3F33; 35 | remoteInfo = LMPullToBounceDemo; 36 | }; 37 | /* End PBXContainerItemProxy section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 1207D3191D7ABC0100DFF2DB /* CircleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CircleLayer.h; sourceTree = ""; }; 41 | 1207D31A1D7ABC0100DFF2DB /* CircleLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CircleLayer.m; sourceTree = ""; }; 42 | 1207D31C1D7ABC5300DFF2DB /* SpinnerLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpinnerLayer.h; sourceTree = ""; }; 43 | 1207D31D1D7ABC5300DFF2DB /* SpinnerLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SpinnerLayer.m; sourceTree = ""; }; 44 | 4860F7F91BA83FBC008BEF70 /* DetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailViewController.h; sourceTree = ""; }; 45 | 4860F7FA1BA83FBC008BEF70 /* DetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailViewController.m; sourceTree = ""; }; 46 | 7DF17C071B84B54D00DD3F33 /* LMPullToBounceDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LMPullToBounceDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | 7DF17C0B1B84B54D00DD3F33 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 48 | 7DF17C0C1B84B54D00DD3F33 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 49 | 7DF17C0E1B84B54D00DD3F33 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 50 | 7DF17C0F1B84B54D00DD3F33 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 51 | 7DF17C111B84B54D00DD3F33 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 52 | 7DF17C121B84B54D00DD3F33 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 53 | 7DF17C151B84B54D00DD3F33 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 54 | 7DF17C171B84B54D00DD3F33 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 55 | 7DF17C1A1B84B54D00DD3F33 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 56 | 7DF17C201B84B54D00DD3F33 /* LMPullToBounceDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LMPullToBounceDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 7DF17C251B84B54D00DD3F33 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 58 | 7DF17C261B84B54D00DD3F33 /* LMPullToBounceDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LMPullToBounceDemoTests.m; sourceTree = ""; }; 59 | 7DF17C481B84B5DD00DD3F33 /* BallView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BallView.h; sourceTree = ""; }; 60 | 7DF17C491B84B5DD00DD3F33 /* BallView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BallView.m; sourceTree = ""; }; 61 | 7DF17C4A1B84B5DD00DD3F33 /* BounceView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BounceView.h; sourceTree = ""; }; 62 | 7DF17C4B1B84B5DD00DD3F33 /* BounceView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BounceView.m; sourceTree = ""; }; 63 | 7DF17C4D1B84B5DD00DD3F33 /* NSTimer+PullToBounce.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSTimer+PullToBounce.h"; sourceTree = ""; }; 64 | 7DF17C4E1B84B5DD00DD3F33 /* NSTimer+PullToBounce.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSTimer+PullToBounce.m"; sourceTree = ""; }; 65 | 7DF17C4F1B84B5DD00DD3F33 /* UIView+PullToBounce.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+PullToBounce.h"; sourceTree = ""; }; 66 | 7DF17C501B84B5DD00DD3F33 /* UIView+PullToBounce.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+PullToBounce.m"; sourceTree = ""; }; 67 | 7DF17C511B84B5DD00DD3F33 /* LMPullToBounceWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LMPullToBounceWrapper.h; sourceTree = ""; }; 68 | 7DF17C521B84B5DD00DD3F33 /* LMPullToBounceWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LMPullToBounceWrapper.m; sourceTree = ""; }; 69 | 7DF17C531B84B5DD00DD3F33 /* SampleTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SampleTableViewCell.h; sourceTree = ""; }; 70 | 7DF17C541B84B5DD00DD3F33 /* SampleTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SampleTableViewCell.m; sourceTree = ""; }; 71 | 7DF17C551B84B5DD00DD3F33 /* WaveView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WaveView.h; sourceTree = ""; }; 72 | 7DF17C561B84B5DD00DD3F33 /* WaveView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WaveView.m; sourceTree = ""; }; 73 | /* End PBXFileReference section */ 74 | 75 | /* Begin PBXFrameworksBuildPhase section */ 76 | 7DF17C041B84B54D00DD3F33 /* Frameworks */ = { 77 | isa = PBXFrameworksBuildPhase; 78 | buildActionMask = 2147483647; 79 | files = ( 80 | ); 81 | runOnlyForDeploymentPostprocessing = 0; 82 | }; 83 | 7DF17C1D1B84B54D00DD3F33 /* Frameworks */ = { 84 | isa = PBXFrameworksBuildPhase; 85 | buildActionMask = 2147483647; 86 | files = ( 87 | ); 88 | runOnlyForDeploymentPostprocessing = 0; 89 | }; 90 | /* End PBXFrameworksBuildPhase section */ 91 | 92 | /* Begin PBXGroup section */ 93 | 7DF17BFE1B84B54D00DD3F33 = { 94 | isa = PBXGroup; 95 | children = ( 96 | 7DF17C091B84B54D00DD3F33 /* LMPullToBounceDemo */, 97 | 7DF17C231B84B54D00DD3F33 /* LMPullToBounceDemoTests */, 98 | 7DF17C081B84B54D00DD3F33 /* Products */, 99 | ); 100 | sourceTree = ""; 101 | }; 102 | 7DF17C081B84B54D00DD3F33 /* Products */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 7DF17C071B84B54D00DD3F33 /* LMPullToBounceDemo.app */, 106 | 7DF17C201B84B54D00DD3F33 /* LMPullToBounceDemoTests.xctest */, 107 | ); 108 | name = Products; 109 | sourceTree = ""; 110 | }; 111 | 7DF17C091B84B54D00DD3F33 /* LMPullToBounceDemo */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 7DF17C471B84B5DD00DD3F33 /* LMPullToBounce */, 115 | 7DF17C0E1B84B54D00DD3F33 /* AppDelegate.h */, 116 | 7DF17C0F1B84B54D00DD3F33 /* AppDelegate.m */, 117 | 7DF17C111B84B54D00DD3F33 /* ViewController.h */, 118 | 7DF17C121B84B54D00DD3F33 /* ViewController.m */, 119 | 7DF17C141B84B54D00DD3F33 /* Main.storyboard */, 120 | 7DF17C171B84B54D00DD3F33 /* Images.xcassets */, 121 | 7DF17C191B84B54D00DD3F33 /* LaunchScreen.xib */, 122 | 7DF17C0A1B84B54D00DD3F33 /* Supporting Files */, 123 | 4860F7F91BA83FBC008BEF70 /* DetailViewController.h */, 124 | 4860F7FA1BA83FBC008BEF70 /* DetailViewController.m */, 125 | ); 126 | path = LMPullToBounceDemo; 127 | sourceTree = ""; 128 | }; 129 | 7DF17C0A1B84B54D00DD3F33 /* Supporting Files */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | 7DF17C0B1B84B54D00DD3F33 /* Info.plist */, 133 | 7DF17C0C1B84B54D00DD3F33 /* main.m */, 134 | ); 135 | name = "Supporting Files"; 136 | sourceTree = ""; 137 | }; 138 | 7DF17C231B84B54D00DD3F33 /* LMPullToBounceDemoTests */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | 7DF17C261B84B54D00DD3F33 /* LMPullToBounceDemoTests.m */, 142 | 7DF17C241B84B54D00DD3F33 /* Supporting Files */, 143 | ); 144 | path = LMPullToBounceDemoTests; 145 | sourceTree = ""; 146 | }; 147 | 7DF17C241B84B54D00DD3F33 /* Supporting Files */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | 7DF17C251B84B54D00DD3F33 /* Info.plist */, 151 | ); 152 | name = "Supporting Files"; 153 | sourceTree = ""; 154 | }; 155 | 7DF17C471B84B5DD00DD3F33 /* LMPullToBounce */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | 1207D31C1D7ABC5300DFF2DB /* SpinnerLayer.h */, 159 | 1207D31D1D7ABC5300DFF2DB /* SpinnerLayer.m */, 160 | 1207D3191D7ABC0100DFF2DB /* CircleLayer.h */, 161 | 1207D31A1D7ABC0100DFF2DB /* CircleLayer.m */, 162 | 7DF17C481B84B5DD00DD3F33 /* BallView.h */, 163 | 7DF17C491B84B5DD00DD3F33 /* BallView.m */, 164 | 7DF17C4A1B84B5DD00DD3F33 /* BounceView.h */, 165 | 7DF17C4B1B84B5DD00DD3F33 /* BounceView.m */, 166 | 7DF17C4C1B84B5DD00DD3F33 /* Category */, 167 | 7DF17C511B84B5DD00DD3F33 /* LMPullToBounceWrapper.h */, 168 | 7DF17C521B84B5DD00DD3F33 /* LMPullToBounceWrapper.m */, 169 | 7DF17C531B84B5DD00DD3F33 /* SampleTableViewCell.h */, 170 | 7DF17C541B84B5DD00DD3F33 /* SampleTableViewCell.m */, 171 | 7DF17C551B84B5DD00DD3F33 /* WaveView.h */, 172 | 7DF17C561B84B5DD00DD3F33 /* WaveView.m */, 173 | ); 174 | path = LMPullToBounce; 175 | sourceTree = SOURCE_ROOT; 176 | }; 177 | 7DF17C4C1B84B5DD00DD3F33 /* Category */ = { 178 | isa = PBXGroup; 179 | children = ( 180 | 7DF17C4D1B84B5DD00DD3F33 /* NSTimer+PullToBounce.h */, 181 | 7DF17C4E1B84B5DD00DD3F33 /* NSTimer+PullToBounce.m */, 182 | 7DF17C4F1B84B5DD00DD3F33 /* UIView+PullToBounce.h */, 183 | 7DF17C501B84B5DD00DD3F33 /* UIView+PullToBounce.m */, 184 | ); 185 | path = Category; 186 | sourceTree = ""; 187 | }; 188 | /* End PBXGroup section */ 189 | 190 | /* Begin PBXNativeTarget section */ 191 | 7DF17C061B84B54D00DD3F33 /* LMPullToBounceDemo */ = { 192 | isa = PBXNativeTarget; 193 | buildConfigurationList = 7DF17C2A1B84B54D00DD3F33 /* Build configuration list for PBXNativeTarget "LMPullToBounceDemo" */; 194 | buildPhases = ( 195 | 7DF17C031B84B54D00DD3F33 /* Sources */, 196 | 7DF17C041B84B54D00DD3F33 /* Frameworks */, 197 | 7DF17C051B84B54D00DD3F33 /* Resources */, 198 | ); 199 | buildRules = ( 200 | ); 201 | dependencies = ( 202 | ); 203 | name = LMPullToBounceDemo; 204 | productName = LMPullToBounceDemo; 205 | productReference = 7DF17C071B84B54D00DD3F33 /* LMPullToBounceDemo.app */; 206 | productType = "com.apple.product-type.application"; 207 | }; 208 | 7DF17C1F1B84B54D00DD3F33 /* LMPullToBounceDemoTests */ = { 209 | isa = PBXNativeTarget; 210 | buildConfigurationList = 7DF17C2D1B84B54D00DD3F33 /* Build configuration list for PBXNativeTarget "LMPullToBounceDemoTests" */; 211 | buildPhases = ( 212 | 7DF17C1C1B84B54D00DD3F33 /* Sources */, 213 | 7DF17C1D1B84B54D00DD3F33 /* Frameworks */, 214 | 7DF17C1E1B84B54D00DD3F33 /* Resources */, 215 | ); 216 | buildRules = ( 217 | ); 218 | dependencies = ( 219 | 7DF17C221B84B54D00DD3F33 /* PBXTargetDependency */, 220 | ); 221 | name = LMPullToBounceDemoTests; 222 | productName = LMPullToBounceDemoTests; 223 | productReference = 7DF17C201B84B54D00DD3F33 /* LMPullToBounceDemoTests.xctest */; 224 | productType = "com.apple.product-type.bundle.unit-test"; 225 | }; 226 | /* End PBXNativeTarget section */ 227 | 228 | /* Begin PBXProject section */ 229 | 7DF17BFF1B84B54D00DD3F33 /* Project object */ = { 230 | isa = PBXProject; 231 | attributes = { 232 | LastUpgradeCheck = 0640; 233 | ORGANIZATIONNAME = com.nju.luckymore; 234 | TargetAttributes = { 235 | 7DF17C061B84B54D00DD3F33 = { 236 | CreatedOnToolsVersion = 6.4; 237 | }; 238 | 7DF17C1F1B84B54D00DD3F33 = { 239 | CreatedOnToolsVersion = 6.4; 240 | TestTargetID = 7DF17C061B84B54D00DD3F33; 241 | }; 242 | }; 243 | }; 244 | buildConfigurationList = 7DF17C021B84B54D00DD3F33 /* Build configuration list for PBXProject "LMPullToBounceDemo" */; 245 | compatibilityVersion = "Xcode 3.2"; 246 | developmentRegion = English; 247 | hasScannedForEncodings = 0; 248 | knownRegions = ( 249 | en, 250 | Base, 251 | ); 252 | mainGroup = 7DF17BFE1B84B54D00DD3F33; 253 | productRefGroup = 7DF17C081B84B54D00DD3F33 /* Products */; 254 | projectDirPath = ""; 255 | projectRoot = ""; 256 | targets = ( 257 | 7DF17C061B84B54D00DD3F33 /* LMPullToBounceDemo */, 258 | 7DF17C1F1B84B54D00DD3F33 /* LMPullToBounceDemoTests */, 259 | ); 260 | }; 261 | /* End PBXProject section */ 262 | 263 | /* Begin PBXResourcesBuildPhase section */ 264 | 7DF17C051B84B54D00DD3F33 /* Resources */ = { 265 | isa = PBXResourcesBuildPhase; 266 | buildActionMask = 2147483647; 267 | files = ( 268 | 7DF17C161B84B54D00DD3F33 /* Main.storyboard in Resources */, 269 | 7DF17C1B1B84B54D00DD3F33 /* LaunchScreen.xib in Resources */, 270 | 7DF17C181B84B54D00DD3F33 /* Images.xcassets in Resources */, 271 | ); 272 | runOnlyForDeploymentPostprocessing = 0; 273 | }; 274 | 7DF17C1E1B84B54D00DD3F33 /* Resources */ = { 275 | isa = PBXResourcesBuildPhase; 276 | buildActionMask = 2147483647; 277 | files = ( 278 | ); 279 | runOnlyForDeploymentPostprocessing = 0; 280 | }; 281 | /* End PBXResourcesBuildPhase section */ 282 | 283 | /* Begin PBXSourcesBuildPhase section */ 284 | 7DF17C031B84B54D00DD3F33 /* Sources */ = { 285 | isa = PBXSourcesBuildPhase; 286 | buildActionMask = 2147483647; 287 | files = ( 288 | 7DF17C5B1B84B5DD00DD3F33 /* LMPullToBounceWrapper.m in Sources */, 289 | 7DF17C5D1B84B5DD00DD3F33 /* WaveView.m in Sources */, 290 | 1207D31E1D7ABC5300DFF2DB /* SpinnerLayer.m in Sources */, 291 | 7DF17C131B84B54D00DD3F33 /* ViewController.m in Sources */, 292 | 1207D31B1D7ABC0100DFF2DB /* CircleLayer.m in Sources */, 293 | 7DF17C5C1B84B5DD00DD3F33 /* SampleTableViewCell.m in Sources */, 294 | 7DF17C101B84B54D00DD3F33 /* AppDelegate.m in Sources */, 295 | 7DF17C5A1B84B5DD00DD3F33 /* UIView+PullToBounce.m in Sources */, 296 | 7DF17C591B84B5DD00DD3F33 /* NSTimer+PullToBounce.m in Sources */, 297 | 4860F7FB1BA83FBC008BEF70 /* DetailViewController.m in Sources */, 298 | 7DF17C581B84B5DD00DD3F33 /* BounceView.m in Sources */, 299 | 7DF17C0D1B84B54D00DD3F33 /* main.m in Sources */, 300 | 7DF17C571B84B5DD00DD3F33 /* BallView.m in Sources */, 301 | ); 302 | runOnlyForDeploymentPostprocessing = 0; 303 | }; 304 | 7DF17C1C1B84B54D00DD3F33 /* Sources */ = { 305 | isa = PBXSourcesBuildPhase; 306 | buildActionMask = 2147483647; 307 | files = ( 308 | 7DF17C271B84B54D00DD3F33 /* LMPullToBounceDemoTests.m in Sources */, 309 | ); 310 | runOnlyForDeploymentPostprocessing = 0; 311 | }; 312 | /* End PBXSourcesBuildPhase section */ 313 | 314 | /* Begin PBXTargetDependency section */ 315 | 7DF17C221B84B54D00DD3F33 /* PBXTargetDependency */ = { 316 | isa = PBXTargetDependency; 317 | target = 7DF17C061B84B54D00DD3F33 /* LMPullToBounceDemo */; 318 | targetProxy = 7DF17C211B84B54D00DD3F33 /* PBXContainerItemProxy */; 319 | }; 320 | /* End PBXTargetDependency section */ 321 | 322 | /* Begin PBXVariantGroup section */ 323 | 7DF17C141B84B54D00DD3F33 /* Main.storyboard */ = { 324 | isa = PBXVariantGroup; 325 | children = ( 326 | 7DF17C151B84B54D00DD3F33 /* Base */, 327 | ); 328 | name = Main.storyboard; 329 | sourceTree = ""; 330 | }; 331 | 7DF17C191B84B54D00DD3F33 /* LaunchScreen.xib */ = { 332 | isa = PBXVariantGroup; 333 | children = ( 334 | 7DF17C1A1B84B54D00DD3F33 /* Base */, 335 | ); 336 | name = LaunchScreen.xib; 337 | sourceTree = ""; 338 | }; 339 | /* End PBXVariantGroup section */ 340 | 341 | /* Begin XCBuildConfiguration section */ 342 | 7DF17C281B84B54D00DD3F33 /* Debug */ = { 343 | isa = XCBuildConfiguration; 344 | buildSettings = { 345 | ALWAYS_SEARCH_USER_PATHS = NO; 346 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 347 | CLANG_CXX_LIBRARY = "libc++"; 348 | CLANG_ENABLE_MODULES = YES; 349 | CLANG_ENABLE_OBJC_ARC = YES; 350 | CLANG_WARN_BOOL_CONVERSION = YES; 351 | CLANG_WARN_CONSTANT_CONVERSION = YES; 352 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 353 | CLANG_WARN_EMPTY_BODY = YES; 354 | CLANG_WARN_ENUM_CONVERSION = YES; 355 | CLANG_WARN_INT_CONVERSION = YES; 356 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 357 | CLANG_WARN_UNREACHABLE_CODE = YES; 358 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 359 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 360 | COPY_PHASE_STRIP = NO; 361 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 362 | ENABLE_STRICT_OBJC_MSGSEND = YES; 363 | GCC_C_LANGUAGE_STANDARD = gnu99; 364 | GCC_DYNAMIC_NO_PIC = NO; 365 | GCC_NO_COMMON_BLOCKS = YES; 366 | GCC_OPTIMIZATION_LEVEL = 0; 367 | GCC_PREPROCESSOR_DEFINITIONS = ( 368 | "DEBUG=1", 369 | "$(inherited)", 370 | ); 371 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 372 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 373 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 374 | GCC_WARN_UNDECLARED_SELECTOR = YES; 375 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 376 | GCC_WARN_UNUSED_FUNCTION = YES; 377 | GCC_WARN_UNUSED_VARIABLE = YES; 378 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 379 | MTL_ENABLE_DEBUG_INFO = YES; 380 | ONLY_ACTIVE_ARCH = YES; 381 | SDKROOT = iphoneos; 382 | }; 383 | name = Debug; 384 | }; 385 | 7DF17C291B84B54D00DD3F33 /* Release */ = { 386 | isa = XCBuildConfiguration; 387 | buildSettings = { 388 | ALWAYS_SEARCH_USER_PATHS = NO; 389 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 390 | CLANG_CXX_LIBRARY = "libc++"; 391 | CLANG_ENABLE_MODULES = YES; 392 | CLANG_ENABLE_OBJC_ARC = YES; 393 | CLANG_WARN_BOOL_CONVERSION = YES; 394 | CLANG_WARN_CONSTANT_CONVERSION = YES; 395 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 396 | CLANG_WARN_EMPTY_BODY = YES; 397 | CLANG_WARN_ENUM_CONVERSION = YES; 398 | CLANG_WARN_INT_CONVERSION = YES; 399 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 400 | CLANG_WARN_UNREACHABLE_CODE = YES; 401 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 402 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 403 | COPY_PHASE_STRIP = NO; 404 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 405 | ENABLE_NS_ASSERTIONS = NO; 406 | ENABLE_STRICT_OBJC_MSGSEND = YES; 407 | GCC_C_LANGUAGE_STANDARD = gnu99; 408 | GCC_NO_COMMON_BLOCKS = YES; 409 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 410 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 411 | GCC_WARN_UNDECLARED_SELECTOR = YES; 412 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 413 | GCC_WARN_UNUSED_FUNCTION = YES; 414 | GCC_WARN_UNUSED_VARIABLE = YES; 415 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 416 | MTL_ENABLE_DEBUG_INFO = NO; 417 | SDKROOT = iphoneos; 418 | VALIDATE_PRODUCT = YES; 419 | }; 420 | name = Release; 421 | }; 422 | 7DF17C2B1B84B54D00DD3F33 /* Debug */ = { 423 | isa = XCBuildConfiguration; 424 | buildSettings = { 425 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 426 | INFOPLIST_FILE = LMPullToBounceDemo/Info.plist; 427 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 428 | PRODUCT_NAME = "$(TARGET_NAME)"; 429 | }; 430 | name = Debug; 431 | }; 432 | 7DF17C2C1B84B54D00DD3F33 /* Release */ = { 433 | isa = XCBuildConfiguration; 434 | buildSettings = { 435 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 436 | INFOPLIST_FILE = LMPullToBounceDemo/Info.plist; 437 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 438 | PRODUCT_NAME = "$(TARGET_NAME)"; 439 | }; 440 | name = Release; 441 | }; 442 | 7DF17C2E1B84B54D00DD3F33 /* Debug */ = { 443 | isa = XCBuildConfiguration; 444 | buildSettings = { 445 | BUNDLE_LOADER = "$(TEST_HOST)"; 446 | FRAMEWORK_SEARCH_PATHS = ( 447 | "$(SDKROOT)/Developer/Library/Frameworks", 448 | "$(inherited)", 449 | ); 450 | GCC_PREPROCESSOR_DEFINITIONS = ( 451 | "DEBUG=1", 452 | "$(inherited)", 453 | ); 454 | INFOPLIST_FILE = LMPullToBounceDemoTests/Info.plist; 455 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 456 | PRODUCT_NAME = "$(TARGET_NAME)"; 457 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LMPullToBounceDemo.app/LMPullToBounceDemo"; 458 | }; 459 | name = Debug; 460 | }; 461 | 7DF17C2F1B84B54D00DD3F33 /* Release */ = { 462 | isa = XCBuildConfiguration; 463 | buildSettings = { 464 | BUNDLE_LOADER = "$(TEST_HOST)"; 465 | FRAMEWORK_SEARCH_PATHS = ( 466 | "$(SDKROOT)/Developer/Library/Frameworks", 467 | "$(inherited)", 468 | ); 469 | INFOPLIST_FILE = LMPullToBounceDemoTests/Info.plist; 470 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 471 | PRODUCT_NAME = "$(TARGET_NAME)"; 472 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LMPullToBounceDemo.app/LMPullToBounceDemo"; 473 | }; 474 | name = Release; 475 | }; 476 | /* End XCBuildConfiguration section */ 477 | 478 | /* Begin XCConfigurationList section */ 479 | 7DF17C021B84B54D00DD3F33 /* Build configuration list for PBXProject "LMPullToBounceDemo" */ = { 480 | isa = XCConfigurationList; 481 | buildConfigurations = ( 482 | 7DF17C281B84B54D00DD3F33 /* Debug */, 483 | 7DF17C291B84B54D00DD3F33 /* Release */, 484 | ); 485 | defaultConfigurationIsVisible = 0; 486 | defaultConfigurationName = Release; 487 | }; 488 | 7DF17C2A1B84B54D00DD3F33 /* Build configuration list for PBXNativeTarget "LMPullToBounceDemo" */ = { 489 | isa = XCConfigurationList; 490 | buildConfigurations = ( 491 | 7DF17C2B1B84B54D00DD3F33 /* Debug */, 492 | 7DF17C2C1B84B54D00DD3F33 /* Release */, 493 | ); 494 | defaultConfigurationIsVisible = 0; 495 | defaultConfigurationName = Release; 496 | }; 497 | 7DF17C2D1B84B54D00DD3F33 /* Build configuration list for PBXNativeTarget "LMPullToBounceDemoTests" */ = { 498 | isa = XCConfigurationList; 499 | buildConfigurations = ( 500 | 7DF17C2E1B84B54D00DD3F33 /* Debug */, 501 | 7DF17C2F1B84B54D00DD3F33 /* Release */, 502 | ); 503 | defaultConfigurationIsVisible = 0; 504 | defaultConfigurationName = Release; 505 | }; 506 | /* End XCConfigurationList section */ 507 | }; 508 | rootObject = 7DF17BFF1B84B54D00DD3F33 /* Project object */; 509 | } 510 | -------------------------------------------------------------------------------- /LMPullToBounceDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LMPullToBounceDemo.xcodeproj/project.xcworkspace/xcshareddata/LMPullToBounceDemo.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 17390C66-59ED-458C-AE23-046B194661CB 9 | IDESourceControlProjectName 10 | LMPullToBounceDemo 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | F58BBED8AFC638FA2D7870072684A155B774B3C1 14 | github.com:luckymore0520/LMPullToBounce.git 15 | 16 | IDESourceControlProjectPath 17 | LMPullToBounceDemo.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | F58BBED8AFC638FA2D7870072684A155B774B3C1 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | github.com:luckymore0520/LMPullToBounce.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | F58BBED8AFC638FA2D7870072684A155B774B3C1 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | F58BBED8AFC638FA2D7870072684A155B774B3C1 36 | IDESourceControlWCCName 37 | LMPullToBounce 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /LMPullToBounceDemo.xcodeproj/project.xcworkspace/xcuserdata/luck-mac.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luckymore0520/LMPullToBounce/19889124c0d53f8597d9756a33abb1e57b5123a0/LMPullToBounceDemo.xcodeproj/project.xcworkspace/xcuserdata/luck-mac.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /LMPullToBounceDemo.xcodeproj/project.xcworkspace/xcuserdata/luckymore.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luckymore0520/LMPullToBounce/19889124c0d53f8597d9756a33abb1e57b5123a0/LMPullToBounceDemo.xcodeproj/project.xcworkspace/xcuserdata/luckymore.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /LMPullToBounceDemo.xcodeproj/xcuserdata/handwHandWinin.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /LMPullToBounceDemo.xcodeproj/xcuserdata/handwHandWinin.xcuserdatad/xcschemes/LMPullToBounceDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /LMPullToBounceDemo.xcodeproj/xcuserdata/handwHandWinin.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | LMPullToBounceDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 7DF17C061B84B54D00DD3F33 16 | 17 | primary 18 | 19 | 20 | 7DF17C1F1B84B54D00DD3F33 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /LMPullToBounceDemo.xcodeproj/xcuserdata/luck-mac.xcuserdatad/xcschemes/LMPullToBounceDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /LMPullToBounceDemo.xcodeproj/xcuserdata/luck-mac.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | LMPullToBounceDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 7DF17C061B84B54D00DD3F33 16 | 17 | primary 18 | 19 | 20 | 7DF17C1F1B84B54D00DD3F33 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /LMPullToBounceDemo.xcodeproj/xcuserdata/luckymore.xcuserdatad/xcschemes/LMPullToBounceDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /LMPullToBounceDemo.xcodeproj/xcuserdata/luckymore.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | LMPullToBounceDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 7DF17C061B84B54D00DD3F33 16 | 17 | primary 18 | 19 | 20 | 7DF17C1F1B84B54D00DD3F33 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /LMPullToBounceDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // WKPullToBounce 4 | // 5 | // Created by luck-mac on 15/8/18. 6 | // Copyright (c) 2015年 com.nju.luckymore. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /LMPullToBounceDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // WKPullToBounce 4 | // 5 | // Created by luck-mac on 15/8/18. 6 | // Copyright (c) 2015年 com.nju.luckymore. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /LMPullToBounceDemo/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 21 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /LMPullToBounceDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /LMPullToBounceDemo/DetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController.h 3 | // LMPullToBounceDemo 4 | // 5 | // Created by Kun Wang on 15/9/15. 6 | // Copyright (c) 2015年 com.nju.luckymore. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DetailViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /LMPullToBounceDemo/DetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController.m 3 | // LMPullToBounceDemo 4 | // 5 | // Created by Kun Wang on 15/9/15. 6 | // Copyright (c) 2015年 com.nju.luckymore. All rights reserved. 7 | // 8 | 9 | #import "DetailViewController.h" 10 | 11 | @implementation DetailViewController 12 | 13 | - (void)viewDidLoad { 14 | [super viewDidLoad]; 15 | [self setTitle:@"Detail"]; 16 | } 17 | 18 | - (void)viewWillAppear:(BOOL)animated { 19 | [super viewWillAppear:animated]; 20 | [self.navigationController setNavigationBarHidden:NO]; 21 | } 22 | 23 | - (IBAction)onDeallocButtonClicked:(id)sender { 24 | UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]]; 25 | UINavigationController *navigationController = [storyboard instantiateInitialViewController]; 26 | [[UIApplication sharedApplication].delegate window].rootViewController = navigationController; 27 | } 28 | @end 29 | -------------------------------------------------------------------------------- /LMPullToBounceDemo/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /LMPullToBounceDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.nju.luckymore.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /LMPullToBounceDemo/SampleTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // SampleTableViewCell.h 3 | // 4 | // 5 | // Created by luck-mac on 15/8/19. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface SampleTableViewCell : UITableViewCell 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /LMPullToBounceDemo/SampleTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // SampleTableViewCell.m 3 | // 4 | // 5 | // Created by luck-mac on 15/8/19. 6 | // 7 | // 8 | 9 | #import "SampleTableViewCell.h" 10 | 11 | @implementation SampleTableViewCell 12 | 13 | - (void)awakeFromNib { 14 | // Initialization code 15 | } 16 | 17 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 18 | [super setSelected:selected animated:animated]; 19 | 20 | // Configure the view for the selected state 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /LMPullToBounceDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // WKPullToBounce 4 | // 5 | // Created by luck-mac on 15/8/18. 6 | // Copyright (c) 2015年 com.nju.luckymore. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /LMPullToBounceDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // WKPullToBounce 4 | // 5 | // Created by luck-mac on 15/8/18. 6 | // Copyright (c) 2015年 com.nju.luckymore. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "UIView+PullToBounce.h" 11 | #import "SampleTableViewCell.h" 12 | #import "LMPullToBounceWrapper.h" 13 | #import "NSTimer+PullToBounce.h" 14 | #define WS(weakSelf) __weak __typeof(&*self)weakSelf = self; 15 | 16 | @interface ViewController () 17 | @property (nonatomic, strong) LMPullToBounceWrapper *pushToBounceWrapper; 18 | @end 19 | 20 | @implementation ViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | [self mockHeader]; 25 | self.view.backgroundColor = [UIColor colorWithRed:0.421593 green:0.657718 blue:0.972549 alpha:1]; 26 | CGRect bodyViewFrame = CGRectMake(0, 20 + 44, self.view.frame.size.width, self.view.frame.size.height); 27 | UIView *bodyView = [[UIView alloc] initWithFrame:bodyViewFrame]; 28 | UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.frame]; 29 | tableView.delegate = self; 30 | tableView.dataSource = self; 31 | [tableView registerClass:[SampleTableViewCell class] forCellReuseIdentifier:NSStringFromClass([SampleTableViewCell class])]; 32 | tableView.separatorStyle = UITableViewCellSeparatorStyleNone; 33 | [self.view addSubview:bodyView]; 34 | self.pushToBounceWrapper = [[LMPullToBounceWrapper alloc] initWithScrollView:tableView]; 35 | [bodyView addSubview:self.pushToBounceWrapper]; 36 | WS(weakSelf); 37 | [self.pushToBounceWrapper setDidPullTorefresh:^(){ 38 | [NSTimer schedule:2.0 handler:^(CFRunLoopTimerRef timer) { 39 | [weakSelf.pushToBounceWrapper stopLoadingAnimation]; 40 | }]; 41 | }]; 42 | // Do any additional setup after loading the view, typically from a nib. 43 | } 44 | 45 | - (void)viewWillAppear:(BOOL)animated { 46 | [super viewWillAppear:animated]; 47 | [self.navigationController setNavigationBarHidden:YES]; 48 | } 49 | 50 | - (void)dealloc { 51 | NSLog(@"old one dealloc succeed"); 52 | } 53 | 54 | - (void)didReceiveMemoryWarning { 55 | [super didReceiveMemoryWarning]; 56 | // Dispose of any resources that can be recreated. 57 | } 58 | 59 | - (void)mockHeader { 60 | UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.width, 64)]; 61 | header.backgroundColor = [UIColor colorWithRed:0.700062 green:0.817345 blue:0.972549 alpha:1]; 62 | [self.view addSubview:header]; 63 | 64 | UIView *headerLine = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 120, 8)]; 65 | headerLine.layer.cornerRadius = headerLine.height; 66 | headerLine.backgroundColor = [UIColor whiteColor]; 67 | headerLine.center = CGPointMake(header.center.x, 20+44/2); 68 | [header addSubview:headerLine]; 69 | } 70 | 71 | #pragma mark - UITableViewDatasource 72 | - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 73 | return 30; 74 | } 75 | 76 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 77 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([SampleTableViewCell class]) forIndexPath:indexPath]; 78 | return cell; 79 | } 80 | 81 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 82 | return 92; 83 | } 84 | 85 | #pragma mark - UITableViewDelegate 86 | - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 87 | [tableView deselectRowAtIndexPath:indexPath animated:NO]; 88 | [self performSegueWithIdentifier:@"detail" sender:nil]; 89 | [self.navigationController setNavigationBarHidden:NO]; 90 | } 91 | @end 92 | -------------------------------------------------------------------------------- /LMPullToBounceDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // WKPullToBounce 4 | // 5 | // Created by luck-mac on 15/8/18. 6 | // Copyright (c) 2015年 com.nju.luckymore. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /LMPullToBounceDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.nju.luckymore.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /LMPullToBounceDemoTests/LMPullToBounceDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // LMPullToBounceDemoTests.m 3 | // LMPullToBounceDemoTests 4 | // 5 | // Created by luck-mac on 15/8/19. 6 | // Copyright (c) 2015年 com.nju.luckymore. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface LMPullToBounceDemoTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation LMPullToBounceDemoTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /LMPullToBounceTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.nju.luckymore.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /LMPullToBounceTests/WKPullToBounceTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // WKPullToBounceTests.m 3 | // WKPullToBounceTests 4 | // 5 | // Created by luck-mac on 15/8/18. 6 | // Copyright (c) 2015年 com.nju.luckymore. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface WKPullToBounceTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation WKPullToBounceTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LMPullToBounce 2 | 3 | The Objective-C version of [PullToBounce](https://github.com/entotsu/PullToBounce). Supports iOS 7.0+. 4 | 5 | ## Usage 6 | See PullToBounce [Usage Part](https://github.com/entotsu/PullToBounce#usage). 7 | 8 | ## Installation 9 | Support CocoaPods 10 | You can add `pod "LMPullToBounce"` to your podfile 11 | You can also add the `LMPullToBounce` folder to your project. 12 | 13 | ## Requirement 14 | + iOS 7.0+ 15 | 16 | ## License 17 | Released under the MIT License. --------------------------------------------------------------------------------