Last active
December 22, 2015 12:39
-
-
Save Shilo/6474058 to your computer and use it in GitHub Desktop.
A UIScrollView subclass that will allow a specified GLKViewController to continue rendering, while scrolling.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// XDGLScrollView.h | |
// A scroll view that will allow a specified GLKViewController to continue rendering, while scrolling. | |
// | |
// Created by Shilo White on 9/7/13. | |
// Copyright (c) 2013 XIDA Design & Technik. All rights reserved. | |
// | |
#import <UIKit/UIKit.h> | |
@class GLKViewController; | |
@interface XDGLScrollView : UIScrollView | |
@property (nonatomic, weak) GLKViewController *glkViewController; | |
@property (nonatomic, readonly) BOOL rendering; | |
@property (nonatomic, readonly) BOOL active; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// XDGLScrollView.m | |
// A scroll view that will allow a specified GLKViewController to continue rendering, while scrolling. | |
// | |
// Created by Shilo White on 9/7/13. | |
// Copyright (c) 2013 XIDA Design & Technik. All rights reserved. | |
// | |
#import "XDGLScrollView.h" | |
#import <GLKit/GLKit.h> | |
#import <QuartzCore/QuartzCore.h> | |
#import <objc/runtime.h> | |
static NSMutableArray *sActiveScrollViews; | |
@interface GLKViewController (XDGLScrollView) | |
@property (nonatomic, weak) XDGLScrollView *_activeScrollView; | |
@end | |
@implementation GLKViewController (XDGLScrollView) | |
- (void)set_activeScrollView:(XDGLScrollView *)_activeScrollView | |
{ | |
objc_setAssociatedObject(self, @selector(_activeScrollView), _activeScrollView, OBJC_ASSOCIATION_ASSIGN); | |
} | |
- (XDGLScrollView *)_activeScrollView | |
{ | |
return objc_getAssociatedObject(self, @selector(_activeScrollView)); | |
} | |
@end | |
@interface XDGLScrollView () <UIScrollViewDelegate> | |
@property (nonatomic, assign) BOOL rendering; | |
@property (nonatomic, assign) BOOL active; | |
+ (NSMutableArray *)activeScrollViews; | |
+ (void)addActiveScrollView:(XDGLScrollView *)scrollView; | |
+ (void)removeActiveScrollView:(XDGLScrollView *)scrollView; | |
+ (XDGLScrollView *)activeScrollViewWithGLKViewController:(GLKViewController *)glkViewController; | |
@end | |
@implementation XDGLScrollView { | |
id<UIScrollViewDelegate> __unsafe_unretained _delegate; | |
GLKViewController __weak *_glkViewController; | |
CADisplayLink *_displayLink; | |
BOOL _active; | |
} | |
@synthesize delegate = _delegate; | |
@synthesize glkViewController = _glkViewController; | |
@synthesize active = _active; | |
- (id)initWithFrame:(CGRect)frame | |
{ | |
if ((self = [super initWithFrame:frame])) | |
{ | |
[self setup]; | |
} | |
return self; | |
} | |
- (id)initWithCoder:(NSCoder *)aDecoder | |
{ | |
if ((self = [super initWithCoder:aDecoder])) | |
{ | |
[self setup]; | |
} | |
return self; | |
} | |
- (id)init | |
{ | |
if ((self = [super init])) | |
{ | |
[self setup]; | |
} | |
return self; | |
} | |
- (void)setup | |
{ | |
super.delegate = self; | |
_glkViewController = nil; | |
_displayLink = nil; | |
_active = NO; | |
} | |
- (void)setRendering:(BOOL)rendering | |
{ | |
if (rendering != self.rendering) | |
{ | |
[_displayLink invalidate]; | |
if (rendering) | |
{ | |
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(render)]; | |
_displayLink.frameInterval = (60/_glkViewController.preferredFramesPerSecond); | |
[_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; | |
} | |
else | |
_displayLink = nil; | |
} | |
} | |
- (BOOL)rendering | |
{ | |
return (_displayLink != nil); | |
} | |
- (void)setActive:(BOOL)active | |
{ | |
if (active != _active) | |
{ | |
_active = active; | |
if (_active) | |
[XDGLScrollView addActiveScrollView:self]; | |
else | |
[XDGLScrollView removeActiveScrollView:self]; | |
} | |
} | |
- (void)render | |
{ | |
[_glkViewController performSelector:@selector(_updateAndDraw)]; | |
} | |
+ (NSMutableArray *)activeScrollViews | |
{ | |
if (!sActiveScrollViews) | |
sActiveScrollViews = [[NSMutableArray alloc] init]; | |
return sActiveScrollViews; | |
} | |
+ (void)addActiveScrollView:(XDGLScrollView *)scrollView | |
{ | |
GLKViewController *glkViewController = scrollView.glkViewController; | |
if (glkViewController && glkViewController._activeScrollView == nil) | |
{ | |
glkViewController._activeScrollView = scrollView; | |
scrollView.rendering = YES; | |
} | |
[[self activeScrollViews] addObject:scrollView]; | |
} | |
+ (void)removeActiveScrollView:(XDGLScrollView *)scrollView | |
{ | |
[[self activeScrollViews] removeObject:scrollView]; | |
GLKViewController *glkViewController = scrollView.glkViewController; | |
if (glkViewController._activeScrollView == scrollView) | |
{ | |
scrollView.rendering = NO; | |
XDGLScrollView *activeScrollView = [self activeScrollViewWithGLKViewController:glkViewController]; | |
glkViewController._activeScrollView = activeScrollView; | |
activeScrollView.rendering = YES; | |
} | |
} | |
+ (XDGLScrollView *)activeScrollViewWithGLKViewController:(GLKViewController *)glkViewController | |
{ | |
for (XDGLScrollView *activeScrollView in sActiveScrollViews) | |
if (activeScrollView.glkViewController == glkViewController) | |
return activeScrollView; | |
return nil; | |
} | |
- (void)scrollViewDidScroll:(UIScrollView *)scrollView | |
{ | |
if ([_delegate respondsToSelector:@selector(scrollViewDidScroll:)]) | |
[_delegate scrollViewDidScroll:scrollView]; | |
} | |
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView | |
{ | |
self.active = YES; | |
if ([_delegate respondsToSelector:@selector(scrollViewWillBeginDragging:)]) | |
[_delegate scrollViewWillBeginDragging:scrollView]; | |
} | |
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset | |
{ | |
if ([_delegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) | |
[_delegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset]; | |
} | |
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate | |
{ | |
if (!decelerate) self.active = NO; | |
if ([_delegate respondsToSelector:@selector(scrollViewDidEndDragging:willDecelerate:)]) | |
[_delegate scrollViewDidEndDragging:scrollView willDecelerate:decelerate]; | |
} | |
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView | |
{ | |
if ([_delegate respondsToSelector:@selector(scrollViewShouldScrollToTop:)]) | |
return [_delegate scrollViewShouldScrollToTop:scrollView]; | |
else | |
return YES; | |
} | |
- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView | |
{ | |
if ([_delegate respondsToSelector:@selector(scrollViewDidScrollToTop:)]) | |
[_delegate scrollViewDidScrollToTop:scrollView]; | |
} | |
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView | |
{ | |
if ([_delegate respondsToSelector:@selector(scrollViewWillBeginDecelerating:)]) | |
[_delegate scrollViewWillBeginDecelerating:scrollView]; | |
} | |
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView | |
{ | |
self.active = NO; | |
if ([_delegate respondsToSelector:@selector(scrollViewDidEndDecelerating:)]) | |
[_delegate scrollViewDidEndDecelerating:scrollView]; | |
} | |
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView | |
{ | |
if ([_delegate respondsToSelector:@selector(viewForZoomingInScrollView:)]) | |
return [_delegate viewForZoomingInScrollView:scrollView]; | |
else | |
return nil; | |
} | |
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view | |
{ | |
if ([_delegate respondsToSelector:@selector(scrollViewWillBeginZooming:withView:)]) | |
[_delegate scrollViewWillBeginZooming:scrollView withView:view]; | |
} | |
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale | |
{ | |
if ([_delegate respondsToSelector:@selector(scrollViewDidEndZooming:withView:atScale:)]) | |
[_delegate scrollViewDidEndZooming:scrollView withView:view atScale:scale]; | |
} | |
- (void)scrollViewDidZoom:(UIScrollView *)scrollView | |
{ | |
if ([_delegate respondsToSelector:@selector(scrollViewDidZoom:)]) | |
[_delegate scrollViewDidZoom:scrollView]; | |
} | |
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView | |
{ | |
if ([_delegate respondsToSelector:@selector(scrollViewDidEndScrollingAnimation:)]) | |
[_delegate scrollViewDidEndScrollingAnimation:scrollView]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment