77
88#import " LXReorderableCollectionViewFlowLayout.h"
99#import < QuartzCore/QuartzCore.h>
10+ #import < objc/runtime.h>
1011
1112#define LX_FRAMES_PER_SECOND 60.0
1213
@@ -28,6 +29,20 @@ typedef NS_ENUM(NSInteger, LXScrollingDirection) {
2829static NSString * const kLXScrollingDirectionKey = @" LXScrollingDirection" ;
2930static NSString * const kLXCollectionViewKeyPath = @" collectionView" ;
3031
32+ @interface CADisplayLink (LX_userInfo)
33+ @property (nonatomic , copy ) NSDictionary *LX_userInfo;
34+ @end
35+
36+ @implementation CADisplayLink (LX_userInfo)
37+ - (void ) setLX_userInfo : (NSDictionary *) LX_userInfo {
38+ objc_setAssociatedObject (self, " LX_userInfo" , LX_userInfo, OBJC_ASSOCIATION_COPY );
39+ }
40+
41+ - (NSDictionary *) LX_userInfo {
42+ return objc_getAssociatedObject (self, " LX_userInfo" );
43+ }
44+ @end
45+
3146@interface UICollectionViewCell (LXReorderableCollectionViewFlowLayout)
3247
3348- (UIImage *)LX_rasterizedImage ;
@@ -52,7 +67,7 @@ @interface LXReorderableCollectionViewFlowLayout ()
5267@property (strong , nonatomic ) UIView *currentView;
5368@property (assign , nonatomic ) CGPoint currentViewCenter;
5469@property (assign , nonatomic ) CGPoint panTranslationInCollectionView;
55- @property (strong , nonatomic ) NSTimer *scrollingTimer ;
70+ @property (strong , nonatomic ) CADisplayLink *displayLink ;
5671
5772@property (assign , nonatomic , readonly ) id <LXReorderableCollectionViewDataSource> dataSource;
5873@property (assign , nonatomic , readonly ) id <LXReorderableCollectionViewDelegateFlowLayout> delegate;
@@ -152,35 +167,34 @@ - (void)invalidateLayoutIfNecessary {
152167}
153168
154169- (void )invalidatesScrollTimer {
155- if (self.scrollingTimer . isValid ) {
156- [self .scrollingTimer invalidate ];
170+ if (! self.displayLink . paused ) {
171+ [self .displayLink invalidate ];
157172 }
158- self.scrollingTimer = nil ;
173+ self.displayLink = nil ;
159174}
160175
161176- (void )setupScrollTimerInDirection : (LXScrollingDirection)direction {
162- if (self.scrollingTimer . isValid ) {
163- LXScrollingDirection oldDirection = [self .scrollingTimer.userInfo [kLXScrollingDirectionKey ] integerValue ];
164-
177+ if (! self.displayLink . paused ) {
178+ LXScrollingDirection oldDirection = [self .displayLink.LX_userInfo [kLXScrollingDirectionKey ] integerValue ];
179+
165180 if (direction == oldDirection) {
166181 return ;
167182 }
168183 }
169184
170185 [self invalidatesScrollTimer ];
171-
172- self.scrollingTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0 / LX_FRAMES_PER_SECOND
173- target: self
174- selector: @selector (handleScroll: )
175- userInfo: @{ kLXScrollingDirectionKey : @(direction) }
176- repeats: YES ];
186+
187+ self.displayLink = [CADisplayLink displayLinkWithTarget: self selector: @selector (handleScroll: )];
188+ self.displayLink .LX_userInfo = @{ kLXScrollingDirectionKey : @(direction) };
189+
190+ [self .displayLink addToRunLoop: [NSRunLoop mainRunLoop ] forMode: NSRunLoopCommonModes ];
177191}
178192
179193#pragma mark - Target/Action methods
180194
181195// Tight loop, allocate memory sparely, even if they are stack allocation.
182- - (void )handleScroll : (NSTimer *)timer {
183- LXScrollingDirection direction = (LXScrollingDirection)[timer.userInfo [kLXScrollingDirectionKey ] integerValue ];
196+ - (void )handleScroll : (CADisplayLink *)displayLink {
197+ LXScrollingDirection direction = (LXScrollingDirection)[displayLink.LX_userInfo [kLXScrollingDirectionKey ] integerValue ];
184198 if (direction == LXScrollingDirectionUnknown) {
185199 return ;
186200 }
0 commit comments