Merge pull request #101 from nguyenhuy/collection_view

Add ASCollectionView
This commit is contained in:
appleguy 2014-11-17 19:03:59 -08:00
commit 3f7dc75bb1
18 changed files with 1144 additions and 18 deletions

View File

@ -132,6 +132,9 @@
05F20AA41A15733C00DCA68A /* ASImageProtocols.h in Headers */ = {isa = PBXBuildFile; fileRef = 05F20AA31A15733C00DCA68A /* ASImageProtocols.h */; settings = {ATTRIBUTES = (Public, ); }; };
3C9C128519E616EF00E942A0 /* ASTableViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C9C128419E616EF00E942A0 /* ASTableViewTests.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
6BDC61F61979037800E50D21 /* AsyncDisplayKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
AC3C4A511A1139C100143C57 /* ASCollectionView.h in Headers */ = {isa = PBXBuildFile; fileRef = AC3C4A4F1A1139C100143C57 /* ASCollectionView.h */; };
AC3C4A521A1139C100143C57 /* ASCollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = AC3C4A501A1139C100143C57 /* ASCollectionView.m */; };
AC3C4A541A113EEC00143C57 /* ASCollectionViewProtocols.h in Headers */ = {isa = PBXBuildFile; fileRef = AC3C4A531A113EEC00143C57 /* ASCollectionViewProtocols.h */; };
DB7121BCD50849C498C886FB /* libPods-AsyncDisplayKitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */; };
/* End PBXBuildFile section */
@ -259,6 +262,9 @@
05F20AA31A15733C00DCA68A /* ASImageProtocols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASImageProtocols.h; sourceTree = "<group>"; };
3C9C128419E616EF00E942A0 /* ASTableViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTableViewTests.m; sourceTree = "<group>"; };
6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AsyncDisplayKit.h; sourceTree = "<group>"; };
AC3C4A4F1A1139C100143C57 /* ASCollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionView.h; sourceTree = "<group>"; };
AC3C4A501A1139C100143C57 /* ASCollectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASCollectionView.m; sourceTree = "<group>"; };
AC3C4A531A113EEC00143C57 /* ASCollectionViewProtocols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionViewProtocols.h; sourceTree = "<group>"; };
D3779BCFF841AD3EB56537ED /* Pods-AsyncDisplayKitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AsyncDisplayKitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests.release.xcconfig"; sourceTree = "<group>"; };
EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AsyncDisplayKitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
FB07EABBCF28656C6297BC2D /* Pods-AsyncDisplayKitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AsyncDisplayKitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests.debug.xcconfig"; sourceTree = "<group>"; };
@ -346,6 +352,9 @@
055F1A3219ABD3E3004DAFF1 /* ASTableView.h */,
0574D5E119C110610097DC25 /* ASTableViewProtocols.h */,
055F1A3319ABD3E3004DAFF1 /* ASTableView.m */,
AC3C4A4F1A1139C100143C57 /* ASCollectionView.h */,
AC3C4A531A113EEC00143C57 /* ASCollectionViewProtocols.h */,
AC3C4A501A1139C100143C57 /* ASCollectionView.m */,
055F1A3A19ABD43F004DAFF1 /* ASCellNode.h */,
055F1A3B19ABD43F004DAFF1 /* ASCellNode.m */,
058D09E1195D050800B7D73C /* Details */,
@ -503,6 +512,7 @@
058D0A48195D05CB00B7D73C /* ASControlNode.m in Headers */,
058D0A49195D05CB00B7D73C /* ASControlNode+Subclasses.h in Headers */,
058D0A4A195D05CB00B7D73C /* ASDisplayNode.h in Headers */,
AC3C4A511A1139C100143C57 /* ASCollectionView.h in Headers */,
058D0A4B195D05CB00B7D73C /* ASDisplayNode.mm in Headers */,
058D0A4C195D05CB00B7D73C /* ASDisplayNode+Subclasses.h in Headers */,
058D0A4D195D05CB00B7D73C /* ASDisplayNodeExtras.h in Headers */,
@ -568,6 +578,7 @@
058D0A7F195D05F900B7D73C /* ASSentinel.h in Headers */,
058D0A80195D05F900B7D73C /* ASSentinel.m in Headers */,
058D0A81195D05F900B7D73C /* ASThread.h in Headers */,
AC3C4A541A113EEC00143C57 /* ASCollectionViewProtocols.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -699,6 +710,7 @@
055F1A3519ABD3E3004DAFF1 /* ASTableView.m in Sources */,
058D0A1D195D050800B7D73C /* ASTextNodeRenderer.mm in Sources */,
058D0A2A195D050800B7D73C /* ASDisplayNode+UIViewBridge.mm in Sources */,
AC3C4A521A1139C100143C57 /* ASCollectionView.m in Sources */,
058D0A20195D050800B7D73C /* ASTextNodeWordKerner.m in Sources */,
058D0A1A195D050800B7D73C /* ASHighlightOverlayLayer.mm in Sources */,
058D0A28195D050800B7D73C /* ASDisplayNode+AsyncDisplay.mm in Sources */,

View File

@ -0,0 +1,111 @@
/* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <UIKit/UIKit.h>
#import <AsyncDisplayKit/ASRangeController.h>
#import <AsyncDisplayKit/ASCollectionViewProtocols.h>
@class ASCellNode;
@protocol ASCollectionViewDataSource;
@protocol ASCollectionViewDelegate;
/**
* Node-based collection view.
*
* ASCollectionView is a version of UICollectionView that uses nodes -- specifically, ASCellNode subclasses -- with asynchronous
* pre-rendering instead of synchronously loading UICollectionViewCells.
*/
@interface ASCollectionView : UICollectionView
@property (nonatomic, weak) id<ASCollectionViewDataSource> asyncDataSource;
@property (nonatomic, weak) id<ASCollectionViewDelegate> asyncDelegate;
/**
* Tuning parameters for the working range.
*
* Defaults to a trailing buffer of one screenful and a leading buffer of two screenfuls.
*/
@property (nonatomic, assign) ASRangeTuningParameters rangeTuningParameters;
/**
* Reload everything from scratch, destroying the working range and all cached nodes.
*
* @warning This method is substantially more expensive than UICollectionView's version.
*/
- (void)reloadData;
/**
* WARNING: ASCollectionView's update/editing support is not yet implemented. Use of these methods will fire an assertion.
*
* This initial version of ASCollectionView only supports appending nodes (see below). If you'd like to see full-fledged
* support for data source updates and interactive editing, please file a GitHub issue -- AsyncDisplayKit can do it,
* we just haven't built it out yet. :]
*/
//- (void)insertSections:(NSIndexSet *)sections;
//- (void)deleteSections:(NSIndexSet *)sections;
//- (void)reloadSections:(NSIndexSet *)sections;
//- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection;
//
//- (void)insertItemsAtIndexPaths:(NSArray *)indexPaths;
//- (void)deleteItemsAtIndexPaths:(NSArray *)indexPaths;
//- (void)reloadItemsAtIndexPaths:(NSArray *)indexPaths;
//- (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath;
/**
* Append nodes.
*
* As with UICollectionView, the asyncDataSource must be updated to reflect the new nodes before this method is called.
*
* @param indexPaths Ordered array of index paths corresponding to the nodes to be added.
*/
- (void)appendNodesWithIndexPaths:(NSArray *)indexPaths;
/**
* Query the sized node at `indexPath` for its calculatedSize.
*
* @param indexPath The index path for the node of interest.
*/
- (CGSize)calculatedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath;
@end
/**
* This is a node-based UICollectionViewDataSource.
*/
@protocol ASCollectionViewDataSource <ASCommonCollectionViewDataSource, NSObject>
/**
* Similar to -collectionView:cellForItemAtIndexPath:.
*
* @param collection The sender.
*
* @param indexPath The index path of the requested node.
*
* @returns a node for display at this indexpath. Must be thread-safe (can be called on the main thread or a background
* queue) and should not implement reuse (it will be called once per row). Unlike UICollectionView's version, this method
* is not called when the row is about to display.
*/
- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForItemAtIndexPath:(NSIndexPath *)indexPath;
@end
/**
* This is a node-based UICollectionViewDelegate.
*/
@protocol ASCollectionViewDelegate <ASCommonCollectionViewDelegate, NSObject>
@optional
- (void)collectionView:(UICollectionView *)collectionView willDisplayNodeForItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingNodeForItemAtIndexPath:(NSIndexPath*)indexPath;
@end

View File

@ -0,0 +1,342 @@
/* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "ASCollectionView.h"
#import "ASAssert.h"
#import "ASRangeController.h"
#pragma mark -
#pragma mark Proxying.
/**
* ASCollectionView intercepts and/or overrides a few of UICollectionView's critical data source and delegate methods.
*
* Any selector included in this function *MUST* be implemented by ASCollectionView.
*/
static BOOL _isInterceptedSelector(SEL sel)
{
return (
// handled by ASCollectionView node<->cell machinery
sel == @selector(collectionView:cellForItemAtIndexPath:) ||
sel == @selector(collectionView:layout:sizeForItemAtIndexPath:) ||
// handled by ASRangeController
sel == @selector(numberOfSectionsInCollectionView:) ||
sel == @selector(collectionView:numberOfItemsInSection:) ||
// used for ASRangeController visibility updates
sel == @selector(collectionView:willDisplayCell:forItemAtIndexPath:) ||
sel == @selector(collectionView:didEndDisplayingCell:forItemAtIndexPath:)
);
}
/**
* Stand-in for UICollectionViewDataSource and UICollectionViewDelegate. Any method calls we intercept are routed to ASCollectionView;
* everything else leaves AsyncDisplayKit safely and arrives at the original intended data source and delegate.
*/
@interface _ASCollectionViewProxy : NSProxy
- (instancetype)initWithTarget:(id<NSObject>)target interceptor:(ASCollectionView *)interceptor;
@end
@implementation _ASCollectionViewProxy {
id<NSObject> __weak _target;
ASCollectionView * __weak _interceptor;
}
- (instancetype)initWithTarget:(id<NSObject>)target interceptor:(ASCollectionView *)interceptor
{
// -[NSProxy init] is undefined
if (!self) {
return nil;
}
ASDisplayNodeAssert(target, @"target must not be nil");
ASDisplayNodeAssert(interceptor, @"interceptor must not be nil");
_target = target;
_interceptor = interceptor;
return self;
}
- (BOOL)respondsToSelector:(SEL)aSelector
{
return (_isInterceptedSelector(aSelector) || [_target respondsToSelector:aSelector]);
}
- (id)forwardingTargetForSelector:(SEL)aSelector
{
if (_isInterceptedSelector(aSelector)) {
return _interceptor;
}
return [_target respondsToSelector:aSelector] ? _target : nil;
}
@end
#pragma mark -
#pragma mark ASCollectionView.
@interface ASCollectionView () <ASRangeControllerDelegate> {
_ASCollectionViewProxy *_proxyDataSource;
_ASCollectionViewProxy *_proxyDelegate;
ASRangeController *_rangeController;
}
@end
@implementation ASCollectionView
#pragma mark -
#pragma mark Lifecycle.
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout
{
if (!(self = [super initWithFrame:frame collectionViewLayout:layout]))
return nil;
_rangeController = [[ASRangeController alloc] init];
_rangeController.delegate = self;
[self registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"_ASCollectionViewCell"];
return self;
}
#pragma mark -
#pragma mark Overrides.
- (void)reloadData
{
[_rangeController rebuildData];
[super reloadData];
}
- (void)setDataSource:(id<UICollectionViewDataSource>)dataSource
{
ASDisplayNodeAssert(NO, @"ASCollectionView uses asyncDataSource, not UICollectionView's dataSource property.");
}
- (void)setDelegate:(id<UICollectionViewDelegate>)delegate
{
// Our UIScrollView superclass sets its delegate to nil on dealloc. Only assert if we get a non-nil value here.
ASDisplayNodeAssert(delegate == nil, @"ASCollectionView uses asyncDelegate, not UICollectionView's delegate property.");
}
- (void)setAsyncDataSource:(id<ASCollectionViewDataSource>)asyncDataSource
{
if (_asyncDataSource == asyncDataSource)
return;
_asyncDataSource = asyncDataSource;
_proxyDataSource = [[_ASCollectionViewProxy alloc] initWithTarget:_asyncDataSource interceptor:self];
super.dataSource = (id<UICollectionViewDataSource>)_proxyDataSource;
}
- (void)setAsyncDelegate:(id<ASCollectionViewDelegate>)asyncDelegate
{
if (_asyncDelegate == asyncDelegate)
return;
_asyncDelegate = asyncDelegate;
_proxyDelegate = [[_ASCollectionViewProxy alloc] initWithTarget:_asyncDelegate interceptor:self];
super.delegate = (id<UICollectionViewDelegate>)_proxyDelegate;
}
- (ASRangeTuningParameters)rangeTuningParameters
{
return _rangeController.tuningParameters;
}
- (void)setRangeTuningParameters:(ASRangeTuningParameters)tuningParameters
{
_rangeController.tuningParameters = tuningParameters;
}
- (void)appendNodesWithIndexPaths:(NSArray *)indexPaths
{
[_rangeController appendNodesWithIndexPaths:indexPaths];
}
- (CGSize)calculatedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath
{
return [_rangeController calculatedSizeForNodeAtIndexPath:indexPath];
}
#pragma mark Assertions.
- (void)throwUnimplementedException
{
[[NSException exceptionWithName:@"UnimplementedException"
reason:@"ASCollectionView's update/editing support is not yet implemented. Please see ASCollectionView.h."
userInfo:nil] raise];
}
- (void)insertSections:(NSIndexSet *)sections
{
[self throwUnimplementedException];
}
- (void)deleteSections:(NSIndexSet *)sections
{
[self throwUnimplementedException];
}
- (void)reloadSections:(NSIndexSet *)sections
{
[self throwUnimplementedException];
}
- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection
{
[self throwUnimplementedException];
}
- (void)insertItemsAtIndexPaths:(NSArray *)indexPaths
{
[self throwUnimplementedException];
}
- (void)deleteItemsAtIndexPaths:(NSArray *)indexPaths
{
[self throwUnimplementedException];
}
- (void)reloadItemsAtIndexPaths:(NSArray *)indexPaths
{
[self throwUnimplementedException];
}
- (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath
{
[self throwUnimplementedException];
}
#pragma mark -
#pragma mark Intercepted selectors.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *reuseIdentifier = @"_ASCollectionViewCell";
UICollectionViewCell *cell = [self dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
[_rangeController configureContentView:cell.contentView forIndexPath:indexPath];
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return [_rangeController calculatedSizeForNodeAtIndexPath:indexPath];
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return [_rangeController numberOfSizedSections];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [_rangeController numberOfSizedRowsInSection:section];
}
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{
[_rangeController visibleNodeIndexPathsDidChange];
if ([_asyncDelegate respondsToSelector:@selector(collectionView:willDisplayNodeForItemAtIndexPath:)]) {
[_asyncDelegate collectionView:self willDisplayNodeForItemAtIndexPath:indexPath];
}
}
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{
[_rangeController visibleNodeIndexPathsDidChange];
if ([_asyncDelegate respondsToSelector:@selector(collectionView:didEndDisplayingNodeForItemAtIndexPath:)]) {
[_asyncDelegate collectionView:self didEndDisplayingNodeForItemAtIndexPath:indexPath];
}
}
#pragma mark -
#pragma mark ASRangeControllerDelegate.
- (NSArray *)rangeControllerVisibleNodeIndexPaths:(ASRangeController *)rangeController
{
ASDisplayNodeAssertMainThread();
return [[self indexPathsForVisibleItems] sortedArrayUsingSelector:@selector(compare:)];
}
- (CGSize)rangeControllerViewportSize:(ASRangeController *)rangeController
{
ASDisplayNodeAssertMainThread();
return self.bounds.size;
}
- (NSInteger)rangeControllerSections:(ASRangeController *)rangeController
{
ASDisplayNodeAssertMainThread();
if ([_asyncDataSource respondsToSelector:@selector(numberOfSectionsInCollectionView:)]) {
return [_asyncDataSource numberOfSectionsInCollectionView:self];
} else {
return 1;
}
}
- (NSInteger)rangeController:(ASRangeController *)rangeController rowsInSection:(NSInteger)section
{
ASDisplayNodeAssertMainThread();
return [_asyncDataSource collectionView:self numberOfItemsInSection:section];
}
- (ASCellNode *)rangeController:(ASRangeController *)rangeController nodeForIndexPath:(NSIndexPath *)indexPath
{
ASDisplayNodeAssertNotMainThread();
return [_asyncDataSource collectionView:self nodeForItemAtIndexPath:indexPath];
}
- (CGSize)rangeController:(ASRangeController *)rangeController constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath
{
ASDisplayNodeAssertNotMainThread();
CGSize contentSize = [self.collectionViewLayout collectionViewContentSize];
CGSize viewSize = self.bounds.size;
CGFloat constrainedWidth = viewSize.width == contentSize.width ? viewSize.width : FLT_MAX;
CGFloat constrainedHeight = viewSize.height == contentSize.height ? viewSize.height : FLT_MAX;
return CGSizeMake(constrainedWidth, constrainedHeight);
}
- (void)rangeController:(ASRangeController *)rangeController didSizeNodesWithIndexPaths:(NSArray *)indexPaths
{
ASDisplayNodeAssertMainThread();
[UIView performWithoutAnimation:^{
[self performBatchUpdates:^{
// -insertItemsAtIndexPaths: is insufficient; UICollectionView also needs to be notified of section changes
NSInteger sectionCount = [super numberOfSections];
NSInteger newSectionCount = [_rangeController numberOfSizedSections];
if (newSectionCount > sectionCount) {
NSRange range = NSMakeRange(sectionCount, newSectionCount - sectionCount);
NSIndexSet *sections = [NSIndexSet indexSetWithIndexesInRange:range];
[super insertSections:sections];
}
[super insertItemsAtIndexPaths:indexPaths];
} completion:nil];
}];
}
@end

View File

@ -0,0 +1,56 @@
/* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
/**
* This is a subset of UICollectionViewDataSource.
*
* @see ASCollectionViewDataSource
*/
@protocol ASCommonCollectionViewDataSource <NSObject>
@required
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section;
@optional
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView;
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;
@end
/**
* This is a subset of UICollectionViewDelegate.
*
* @see ASCollectionViewDelegate
*/
@protocol ASCommonCollectionViewDelegate <NSObject, UIScrollViewDelegate>
@optional
- (UICollectionViewTransitionLayout *)collectionView:(UICollectionView *)collectionView transitionLayoutForOldLayout:(UICollectionViewLayout *)fromLayout newLayout:(UICollectionViewLayout *)toLayout;
- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath;
- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath;
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath;
- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath;
- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath;
- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender;
- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender;
@end

View File

@ -16,4 +16,5 @@
#import <AsyncDisplayKit/ASMultiplexImageNode.h>
#import <AsyncDisplayKit/ASTableView.h>
#import <AsyncDisplayKit/ASCollectionView.h>
#import <AsyncDisplayKit/ASCellNode.h>

View File

@ -14,8 +14,8 @@
#import "ASRangeControllerInternal.h"
typedef NS_ENUM(NSInteger, ASScrollDirection) {
ASScrollDirectionUp,
ASScrollDirectionDown,
ASScrollDirectionBackward,
ASScrollDirectionForward,
};
@interface ASRangeController () {
@ -283,7 +283,7 @@ static BOOL ASRangeIsValid(NSRange range)
_visibleRange = _workingRange = NSMakeRange(NSNotFound, 0);
_sizedNodeCount = 0;
_nodeSizes = [NSMutableArray array];
_scrollDirection = ASScrollDirectionDown;
_scrollDirection = ASScrollDirectionForward;
_workingIndexPaths = [NSMutableOrderedSet orderedSet];
// don't bother sizing if the data source is empty
@ -413,34 +413,38 @@ static NSRange ASCalculateWorkingRange(ASRangeTuningParameters params, ASScrollD
ASDisplayNodeCAssert(NSMaxRange(visibleRange) <= nodeSizes.count, @"nodes can't be visible until they're sized");
// extend the visible range by enough nodes to fill at least the requested number of screenfuls
// NB. this logic assumes (UITableView-style) vertical scrolling and would need to be changed for ASCollectionView
// NB. this logic assumes there is no overlap between nodes. It also doesn't
// take spacing between nodes into account.
CGFloat viewportArea = viewport.width * viewport.height;
CGFloat minUpperBufferSize, minLowerBufferSize;
switch (scrollDirection) {
case ASScrollDirectionUp:
minUpperBufferSize = viewport.height * params.leadingBufferScreenfuls;
minLowerBufferSize = viewport.height * params.trailingBufferScreenfuls;
case ASScrollDirectionBackward:
minUpperBufferSize = viewportArea * params.leadingBufferScreenfuls;
minLowerBufferSize = viewportArea * params.trailingBufferScreenfuls;
break;
case ASScrollDirectionDown:
minUpperBufferSize = viewport.height * params.trailingBufferScreenfuls;
minLowerBufferSize = viewport.height * params.leadingBufferScreenfuls;
case ASScrollDirectionForward:
minUpperBufferSize = viewportArea * params.trailingBufferScreenfuls;
minLowerBufferSize = viewportArea * params.leadingBufferScreenfuls;
break;
}
// "top" buffer (above the screen, if we're scrolling vertically)
NSInteger upperBuffer = 0;
CGFloat upperBufferHeight = 0.0f;
for (NSInteger idx = visibleRange.location - 1; idx >= 0 && upperBufferHeight < minUpperBufferSize; idx--) {
CGFloat upperBufferArea = 0.0f;
for (NSInteger idx = visibleRange.location - 1; idx >= 0 && upperBufferArea < minUpperBufferSize; idx--) {
upperBuffer++;
upperBufferHeight += [nodeSizes[idx] CGSizeValue].height;
CGSize nodeSize = [nodeSizes[idx] CGSizeValue];
upperBufferArea += nodeSize.width * nodeSize.height;
}
// "bottom" buffer (below the screen, if we're scrolling vertically)
NSInteger lowerBuffer = 0;
CGFloat lowerBufferHeight = 0.0f;
for (NSInteger idx = NSMaxRange(visibleRange); idx < nodeSizes.count && lowerBufferHeight < minLowerBufferSize; idx++) {
CGFloat lowerBufferArea = 0.0f;
for (NSInteger idx = NSMaxRange(visibleRange); idx < nodeSizes.count && lowerBufferArea < minLowerBufferSize; idx++) {
lowerBuffer++;
lowerBufferHeight += [nodeSizes[idx] CGSizeValue].height;
CGSize nodeSize = [nodeSizes[idx] CGSizeValue];
lowerBufferArea += nodeSize.width * nodeSize.height;
}
return NSMakeRange(visibleRange.location - upperBuffer,
@ -459,9 +463,9 @@ static NSRange ASCalculateWorkingRange(ASRangeTuningParameters params, ASScrollD
// figure out where we're going, because that's where the bulk of the working range needs to be
NSInteger scrollDelta = _visibleRange.location - previouslyVisible.location;
if (scrollDelta < 0)
_scrollDirection = ASScrollDirectionUp;
_scrollDirection = ASScrollDirectionBackward;
if (scrollDelta > 0)
_scrollDirection = ASScrollDirectionDown;
_scrollDirection = ASScrollDirectionForward;
[self recalculateWorkingRange];
}

View File

@ -0,0 +1,340 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
AC3C4A641A11F47200143C57 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = AC3C4A631A11F47200143C57 /* main.m */; };
AC3C4A671A11F47200143C57 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = AC3C4A661A11F47200143C57 /* AppDelegate.m */; };
AC3C4A6A1A11F47200143C57 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AC3C4A691A11F47200143C57 /* ViewController.m */; };
AC3C4A8E1A11F80C00143C57 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AC3C4A8D1A11F80C00143C57 /* Images.xcassets */; };
FABD6D156A3EB118497E5CE6 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F02BAF78E68BC56FD8C161B7 /* libPods.a */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
2DBAEE96397BB913350C4530 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
AC3C4A5E1A11F47200143C57 /* CollectionViewSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CollectionViewSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
AC3C4A621A11F47200143C57 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
AC3C4A631A11F47200143C57 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
AC3C4A651A11F47200143C57 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
AC3C4A661A11F47200143C57 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
AC3C4A681A11F47200143C57 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
AC3C4A691A11F47200143C57 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
AC3C4A8D1A11F80C00143C57 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
CD1ABB23007FEDB31D8C1978 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
F02BAF78E68BC56FD8C161B7 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
AC3C4A5B1A11F47200143C57 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FABD6D156A3EB118497E5CE6 /* libPods.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
90A2B9C5397C46134C8A793B /* Pods */ = {
isa = PBXGroup;
children = (
2DBAEE96397BB913350C4530 /* Pods.debug.xcconfig */,
CD1ABB23007FEDB31D8C1978 /* Pods.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
AC3C4A551A11F47200143C57 = {
isa = PBXGroup;
children = (
AC3C4A601A11F47200143C57 /* CollectionViewSample */,
AC3C4A5F1A11F47200143C57 /* Products */,
90A2B9C5397C46134C8A793B /* Pods */,
D6E38FF0CB18E3F55CF06437 /* Frameworks */,
);
sourceTree = "<group>";
};
AC3C4A5F1A11F47200143C57 /* Products */ = {
isa = PBXGroup;
children = (
AC3C4A5E1A11F47200143C57 /* CollectionViewSample.app */,
);
name = Products;
sourceTree = "<group>";
};
AC3C4A601A11F47200143C57 /* CollectionViewSample */ = {
isa = PBXGroup;
children = (
AC3C4A651A11F47200143C57 /* AppDelegate.h */,
AC3C4A661A11F47200143C57 /* AppDelegate.m */,
AC3C4A681A11F47200143C57 /* ViewController.h */,
AC3C4A691A11F47200143C57 /* ViewController.m */,
AC3C4A8D1A11F80C00143C57 /* Images.xcassets */,
AC3C4A611A11F47200143C57 /* Supporting Files */,
);
path = CollectionViewSample;
sourceTree = "<group>";
};
AC3C4A611A11F47200143C57 /* Supporting Files */ = {
isa = PBXGroup;
children = (
AC3C4A621A11F47200143C57 /* Info.plist */,
AC3C4A631A11F47200143C57 /* main.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
D6E38FF0CB18E3F55CF06437 /* Frameworks */ = {
isa = PBXGroup;
children = (
F02BAF78E68BC56FD8C161B7 /* libPods.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
AC3C4A5D1A11F47200143C57 /* CollectionViewSample */ = {
isa = PBXNativeTarget;
buildConfigurationList = AC3C4A811A11F47200143C57 /* Build configuration list for PBXNativeTarget "CollectionViewSample" */;
buildPhases = (
F868CFBB21824CC9521B6588 /* Check Pods Manifest.lock */,
AC3C4A5A1A11F47200143C57 /* Sources */,
AC3C4A5B1A11F47200143C57 /* Frameworks */,
AC3C4A5C1A11F47200143C57 /* Resources */,
A6902C454C7661D0D277AC62 /* Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
);
name = CollectionViewSample;
productName = CollectionViewSample;
productReference = AC3C4A5E1A11F47200143C57 /* CollectionViewSample.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
AC3C4A561A11F47200143C57 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0610;
ORGANIZATIONNAME = Facebook;
TargetAttributes = {
AC3C4A5D1A11F47200143C57 = {
CreatedOnToolsVersion = 6.1;
};
};
};
buildConfigurationList = AC3C4A591A11F47200143C57 /* Build configuration list for PBXProject "CollectionViewSample" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = AC3C4A551A11F47200143C57;
productRefGroup = AC3C4A5F1A11F47200143C57 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
AC3C4A5D1A11F47200143C57 /* CollectionViewSample */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
AC3C4A5C1A11F47200143C57 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
AC3C4A8E1A11F80C00143C57 /* Images.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
A6902C454C7661D0D277AC62 /* Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
showEnvVarsInLog = 0;
};
F868CFBB21824CC9521B6588 /* Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
AC3C4A5A1A11F47200143C57 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
AC3C4A6A1A11F47200143C57 /* ViewController.m in Sources */,
AC3C4A671A11F47200143C57 /* AppDelegate.m in Sources */,
AC3C4A641A11F47200143C57 /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
AC3C4A7F1A11F47200143C57 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
AC3C4A801A11F47200143C57 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
AC3C4A821A11F47200143C57 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 2DBAEE96397BB913350C4530 /* Pods.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
INFOPLIST_FILE = CollectionViewSample/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = 1;
};
name = Debug;
};
AC3C4A831A11F47200143C57 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = CD1ABB23007FEDB31D8C1978 /* Pods.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
INFOPLIST_FILE = CollectionViewSample/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = 1;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
AC3C4A591A11F47200143C57 /* Build configuration list for PBXProject "CollectionViewSample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
AC3C4A7F1A11F47200143C57 /* Debug */,
AC3C4A801A11F47200143C57 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
AC3C4A811A11F47200143C57 /* Build configuration list for PBXNativeTarget "CollectionViewSample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
AC3C4A821A11F47200143C57 /* Debug */,
AC3C4A831A11F47200143C57 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = AC3C4A561A11F47200143C57 /* Project object */;
}

View File

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

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:CollectionViewSample.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@ -0,0 +1,15 @@
//
// AppDelegate.h
// CollectionViewSample
//
// Created by Huy Nguyen on 11/11/14.
// Copyright (c) 2014 Facebook. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end

View File

@ -0,0 +1,26 @@
/* This file provided by Facebook is for non-commercial testing and evaluation
* purposes only. Facebook reserves all rights not expressly granted.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#import "AppDelegate.h"
#import "ViewController.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
self.window.rootViewController = [[ViewController alloc] init];
[self.window makeKeyAndVisible];
return YES;
}
@end

View File

@ -0,0 +1,39 @@
{
"images" : [
{
"orientation" : "portrait",
"idiom" : "iphone",
"filename" : "Default-568h@2x.png",
"minimum-system-version" : "7.0",
"subtype" : "retina4",
"scale" : "2x"
},
{
"idiom" : "iphone",
"scale" : "1x",
"orientation" : "portrait"
},
{
"idiom" : "iphone",
"scale" : "2x",
"orientation" : "portrait"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"filename" : "Default-568h@2x.png",
"subtype" : "retina4",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"minimum-system-version" : "7.0",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

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

View File

@ -0,0 +1,16 @@
/* This file provided by Facebook is for non-commercial testing and evaluation
* purposes only. Facebook reserves all rights not expressly granted.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end

View File

@ -0,0 +1,81 @@
/* This file provided by Facebook is for non-commercial testing and evaluation
* purposes only. Facebook reserves all rights not expressly granted.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#import "ViewController.h"
#import <AsyncDisplayKit/AsyncDisplayKit.h>
@interface ViewController () <ASCollectionViewDataSource, ASCollectionViewDelegate>
{
ASCollectionView *_collectionView;
}
@end
@implementation ViewController
#pragma mark -
#pragma mark UIViewController.
- (instancetype)init
{
if (!(self = [super init]))
return nil;
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
_collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
_collectionView.asyncDataSource = self;
_collectionView.asyncDelegate = self;
_collectionView.backgroundColor = [UIColor whiteColor];
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view addSubview:_collectionView];
}
- (void)viewWillLayoutSubviews
{
_collectionView.frame = self.view.bounds;
}
- (BOOL)prefersStatusBarHidden
{
return YES;
}
#pragma mark -
#pragma mark ASCollectionView data source.
- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSString *text = [NSString stringWithFormat:@"[%ld.%ld] says hi", indexPath.section, indexPath.item];
ASTextCellNode *node = [[ASTextCellNode alloc] init];
node.text = text;
node.backgroundColor = [UIColor lightGrayColor];
return node;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 300;
}
@end

View File

@ -0,0 +1,16 @@
//
// main.m
// CollectionViewSample
//
// Created by Huy Nguyen on 11/11/14.
// Copyright (c) 2014 Facebook. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

View File

@ -0,0 +1,3 @@
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
pod 'AsyncDisplayKit', :path => '../..'