Merge branch 'master' into RemoveWorkingWindow

This commit is contained in:
Scott Goodson 2015-12-18 18:25:14 -08:00
commit c6759671e6
37 changed files with 1023 additions and 95 deletions

Binary file not shown.

View File

@ -190,6 +190,10 @@
258FF4281C0D152600A83844 /* ASRangeHandlerVisible.mm in Sources */ = {isa = PBXBuildFile; fileRef = 258FF4261C0D152600A83844 /* ASRangeHandlerVisible.mm */; };
25A977EF1C0D2A5500406B62 /* ASRangeHandlerVisible.mm in Sources */ = {isa = PBXBuildFile; fileRef = 258FF4261C0D152600A83844 /* ASRangeHandlerVisible.mm */; };
25BAA16F1C0D18D2002747C7 /* ASRangeHandlerVisible.h in Headers */ = {isa = PBXBuildFile; fileRef = 258FF4251C0D152600A83844 /* ASRangeHandlerVisible.h */; };
25E327561C16819500A2170C /* ASPagerNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 25E327541C16819500A2170C /* ASPagerNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
25E327571C16819500A2170C /* ASPagerNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 25E327541C16819500A2170C /* ASPagerNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
25E327581C16819500A2170C /* ASPagerNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E327551C16819500A2170C /* ASPagerNode.m */; };
25E327591C16819500A2170C /* ASPagerNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E327551C16819500A2170C /* ASPagerNode.m */; };
2767E9411BB19BD600EA9B77 /* ASViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = ACC945A81BA9E7A0005E1FB8 /* ASViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
2767E9421BB19BD600EA9B77 /* ASViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = ACC945AA1BA9E7C1005E1FB8 /* ASViewController.m */; };
2911485C1A77147A005D0878 /* ASControlNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2911485B1A77147A005D0878 /* ASControlNodeTests.m */; };
@ -523,7 +527,7 @@
057D02C51AC0A66700C7AC3C /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
057D02C61AC0A66700C7AC3C /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
0587F9BB1A7309ED00AFF0BA /* ASEditableTextNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASEditableTextNode.h; sourceTree = "<group>"; };
0587F9BC1A7309ED00AFF0BA /* ASEditableTextNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASEditableTextNode.mm; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
0587F9BC1A7309ED00AFF0BA /* ASEditableTextNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASEditableTextNode.mm; sourceTree = "<group>"; };
058D09AC195D04C000B7D73C /* libAsyncDisplayKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libAsyncDisplayKit.a; sourceTree = BUILT_PRODUCTS_DIR; };
058D09AF195D04C000B7D73C /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
058D09B3195D04C000B7D73C /* AsyncDisplayKit-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AsyncDisplayKit-Prefix.pch"; sourceTree = "<group>"; };
@ -644,6 +648,8 @@
257754BD1BEE458E00737CA5 /* ASTextNodeWordKerner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASTextNodeWordKerner.m; path = TextKit/ASTextNodeWordKerner.m; sourceTree = "<group>"; };
258FF4251C0D152600A83844 /* ASRangeHandlerVisible.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASRangeHandlerVisible.h; sourceTree = "<group>"; };
258FF4261C0D152600A83844 /* ASRangeHandlerVisible.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASRangeHandlerVisible.mm; sourceTree = "<group>"; };
25E327541C16819500A2170C /* ASPagerNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPagerNode.h; sourceTree = "<group>"; };
25E327551C16819500A2170C /* ASPagerNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPagerNode.m; sourceTree = "<group>"; };
2911485B1A77147A005D0878 /* ASControlNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASControlNodeTests.m; sourceTree = "<group>"; };
292C59991A956527007E5DD6 /* ASLayoutRangeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutRangeType.h; sourceTree = "<group>"; };
292C599A1A956527007E5DD6 /* ASRangeHandlerPreload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASRangeHandlerPreload.h; sourceTree = "<group>"; };
@ -893,6 +899,8 @@
0516FA3F1A1563D200B4EBED /* ASMultiplexImageNode.mm */,
055B9FA61A1C154B00035D6D /* ASNetworkImageNode.h */,
055B9FA71A1C154B00035D6D /* ASNetworkImageNode.mm */,
25E327541C16819500A2170C /* ASPagerNode.h */,
25E327551C16819500A2170C /* ASPagerNode.m */,
D785F6601A74327E00291744 /* ASScrollNode.h */,
D785F6611A74327E00291744 /* ASScrollNode.m */,
B0F880581BEAEC7500D17647 /* ASTableNode.h */,
@ -1246,6 +1254,7 @@
058D0A83195D060300B7D73C /* ASBaseDefines.h in Headers */,
054963491A1EA066000F8E56 /* ASBasicImageDownloader.h in Headers */,
2967F9E21AB0A5190072E4AB /* ASBasicImageDownloaderInternal.h in Headers */,
25E327561C16819500A2170C /* ASPagerNode.h in Headers */,
299DA1A91A828D2900162D41 /* ASBatchContext.h in Headers */,
251B8EF91BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.h in Headers */,
044285071BAA63FE00D16268 /* ASBatchFetching.h in Headers */,
@ -1438,6 +1447,7 @@
B350622D1B010EFD0018CF92 /* ASScrollDirection.h in Headers */,
254C6B751BF94DF4003EC431 /* ASTextKitHelpers.h in Headers */,
B35062081B010EFD0018CF92 /* ASScrollNode.h in Headers */,
25E327571C16819500A2170C /* ASPagerNode.h in Headers */,
B35062551B010EFD0018CF92 /* ASSentinel.h in Headers */,
9C8221961BA237B80037F19A /* ASStackBaselinePositionedLayout.h in Headers */,
9C49C3701B853961000B0DD5 /* ASStackLayoutable.h in Headers */,
@ -1687,6 +1697,7 @@
058D0A28195D050800B7D73C /* ASDisplayNode+AsyncDisplay.mm in Sources */,
058D0A29195D050800B7D73C /* ASDisplayNode+DebugTiming.mm in Sources */,
058D0A2A195D050800B7D73C /* ASDisplayNode+UIViewBridge.mm in Sources */,
25E327581C16819500A2170C /* ASPagerNode.m in Sources */,
058D0A14195D050800B7D73C /* ASDisplayNode.mm in Sources */,
058D0A15195D050800B7D73C /* ASDisplayNodeExtras.mm in Sources */,
0587F9BE1A7309ED00AFF0BA /* ASEditableTextNode.mm in Sources */,
@ -1815,6 +1826,7 @@
B350621A1B010EFD0018CF92 /* ASDealloc2MainObject.m in Sources */,
34EFC75C1B701BD200AD841F /* ASDimension.mm in Sources */,
B350624E1B010EFD0018CF92 /* ASDisplayNode+AsyncDisplay.mm in Sources */,
25E327591C16819500A2170C /* ASPagerNode.m in Sources */,
B35062501B010EFD0018CF92 /* ASDisplayNode+DebugTiming.mm in Sources */,
254C6B891BF94F8A003EC431 /* ASTextKitRenderer+Positioning.mm in Sources */,
B35062511B010EFD0018CF92 /* ASDisplayNode+UIViewBridge.mm in Sources */,

View File

@ -6,7 +6,7 @@
// Copyright (c) 2015 Facebook. All rights reserved.
//
#import <AsyncDisplayKit/AsyncDisplayKit.h>
#import <AsyncDisplayKit/ASCollectionView.h>
/**
* ASCollectionNode is a node based class that wraps an ASCollectionView. It can be used

View File

@ -7,6 +7,7 @@
//
#import "ASCollectionNode.h"
#import "ASDisplayNode+Subclasses.h"
@implementation ASCollectionNode

View File

@ -685,7 +685,6 @@ typedef NS_OPTIONS(NSUInteger, ASInterfaceState)
* @param node The node to be added.
*/
- (void)addSubnode:(ASDisplayNode *)node;
- (NSString *)name;
@end
/** CALayer(AsyncDisplayKit) defines convenience method for adding sub-ASDisplayNode to a CALayer. */
@ -696,7 +695,6 @@ typedef NS_OPTIONS(NSUInteger, ASInterfaceState)
* @param node The node to be added.
*/
- (void)addSubnode:(ASDisplayNode *)node;
- (NSString *)name;
@end
@interface ASDisplayNode (Deprecated)

View File

@ -1849,8 +1849,28 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
CGRect subnodeFrame = CGRectZero;
for (ASLayout *subnodeLayout in _layout.sublayouts) {
ASDisplayNodeAssert([_subnodes containsObject:subnodeLayout.layoutableObject], @"Cached sublayouts must only contain subnodes' layout.");
subnodeFrame.origin = subnodeLayout.position;
subnodeFrame.size = subnodeLayout.size;
CGPoint adjustedOrigin = subnodeLayout.position;
if (isfinite(adjustedOrigin.x) == NO) {
ASDisplayNodeAssert(0, @"subnodeLayout has an invalid position");
adjustedOrigin.x = 0;
}
if (isfinite(adjustedOrigin.y) == NO) {
ASDisplayNodeAssert(0, @"subnodeLayout has an invalid position");
adjustedOrigin.y = 0;
}
subnodeFrame.origin = adjustedOrigin;
CGSize adjustedSize = subnodeLayout.size;
if (isfinite(adjustedSize.width) == NO) {
ASDisplayNodeAssert(0, @"subnodeLayout has an invalid size");
adjustedSize.width = 0;
}
if (isfinite(adjustedSize.height) == NO) {
ASDisplayNodeAssert(0, @"subnodeLayout has an invalid position");
adjustedSize.height = 0;
}
subnodeFrame.size = adjustedSize;
subnode = ((ASDisplayNode *)subnodeLayout.layoutableObject);
[subnode setFrame:subnodeFrame];
}
@ -2293,11 +2313,6 @@ static const char *ASDisplayNodeAssociatedNodeKey = "ASAssociatedNode";
}
}
- (NSString *)name
{
return self.asyncdisplaykit_node.name;
}
@end
@implementation CALayer (AsyncDisplayKit)
@ -2307,11 +2322,6 @@ static const char *ASDisplayNodeAssociatedNodeKey = "ASAssociatedNode";
[self addSublayer:node.layer];
}
- (NSString *)name
{
return self.asyncdisplaykit_node.name;
}
@end

View File

@ -124,7 +124,6 @@
textView.opaque = NO;
}
textView.textContainerInset = self.textContainerInset;
textView.clipsToBounds = NO; // We don't want selection handles cut off.
};
// Create and configure the placeholder text view.

View File

@ -11,7 +11,10 @@
@interface ASMapNode : ASImageNode
- (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate NS_DESIGNATED_INITIALIZER;
/**
The current region of ASMapNode. This can be set at any time and ASMapNode will animate the change.
*/
@property (nonatomic, assign) MKCoordinateRegion region;
/**
This is the MKMapView that is the live map part of ASMapNode. This will be nil if .liveMap = NO. Note, MKMapView is *not* thread-safe.

View File

@ -17,70 +17,80 @@
MKMapSnapshotter *_snapshotter;
MKMapSnapshotOptions *_options;
NSArray *_annotations;
ASDisplayNode *_mapNode;
CLLocationCoordinate2D _centerCoordinateOfMap;
}
@end
@implementation ASMapNode
@synthesize liveMap = _liveMap;
@synthesize needsMapReloadOnBoundsChange = _needsMapReloadOnBoundsChange;
@synthesize mapDelegate = _mapDelegate;
@synthesize region = _region;
- (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate
#pragma mark - Lifecycle
- (instancetype)init
{
if (!(self = [super init])) {
return nil;
}
self.backgroundColor = ASDisplayNodeDefaultPlaceholderColor();
self.clipsToBounds = YES;
_needsMapReloadOnBoundsChange = YES;
_liveMap = NO;
_centerCoordinateOfMap = kCLLocationCoordinate2DInvalid;
_region = MKCoordinateRegionMake(CLLocationCoordinate2DMake(43.432858, 13.183671), MKCoordinateSpanMake(0.2, 0.2));
_options = [[MKMapSnapshotOptions alloc] init];
_options.region = MKCoordinateRegionMakeWithDistance(coordinate, 1000, 1000);;
_options.region = _region;
return self;
}
- (void)setAnnotations:(NSArray *)annotations
- (void)didLoad
{
ASDN::MutexLocker l(_propertyLock);
_annotations = [annotations copy];
if (annotations.count != _annotations.count) {
// Redraw
[self setNeedsDisplay];
[super didLoad];
if ([self wasLiveMapPreviously]) {
self.userInteractionEnabled = YES;
[self addLiveMap];
}
}
- (void)setUpSnapshotter
- (void)fetchData
{
if (!_snapshotter) {
ASDisplayNodeAssert(!CGSizeEqualToSize(CGSizeZero, self.calculatedSize), @"self.calculatedSize can not be zero. Make sure that you are setting a preferredFrameSize or wrapping ASMapNode in a ASRatioLayoutSpec or similar.");
_options.size = self.calculatedSize;
_snapshotter = [[MKMapSnapshotter alloc] initWithOptions:_options];
[super fetchData];
if ([self wasLiveMapPreviously]) {
[self addLiveMap];
} else {
[self setUpSnapshotter];
[self takeSnapshot];
}
}
- (void)clearFetchedData
{
[super clearFetchedData];
if (self.isLiveMap) {
[self removeLiveMap];
}
}
#pragma mark - Settings
- (BOOL)isLiveMap
{
ASDN::MutexLocker l(_propertyLock);
return _liveMap;
return (_mapView != nil);
}
- (void)setLiveMap:(BOOL)liveMap
{
ASDN::MutexLocker l(_propertyLock);
if (liveMap == _liveMap) {
return;
}
_liveMap = liveMap;
liveMap ? [self addLiveMap] : [self removeLiveMap];
}
- (BOOL)wasLiveMapPreviously
{
return CLLocationCoordinate2DIsValid(_centerCoordinateOfMap);
}
- (BOOL)needsMapReloadOnBoundsChange
{
@ -94,23 +104,26 @@
_needsMapReloadOnBoundsChange = needsMapReloadOnBoundsChange;
}
- (void)fetchData
- (MKCoordinateRegion)region
{
[super fetchData];
if (_liveMap && !_mapNode) {
[self addLiveMap];
}
else {
[self setUpSnapshotter];
ASDN::MutexLocker l(_propertyLock);
return _region;
}
- (void)setRegion:(MKCoordinateRegion)region
{
ASDN::MutexLocker l(_propertyLock);
_region = region;
if (self.isLiveMap) {
[_mapView setRegion:_region animated:YES];
} else {
_options.region = _region;
[self resetSnapshotter];
[self takeSnapshot];
}
}
- (void)clearFetchedData
{
[super clearFetchedData];
[self removeLiveMap];
}
#pragma mark - Snapshotter
- (void)takeSnapshot
{
@ -150,42 +163,60 @@
}
}
- (void)resetSnapshotter
- (void)setUpSnapshotter
{
if (!_snapshotter.isLoading) {
if (!_snapshotter) {
ASDisplayNodeAssert(!CGSizeEqualToSize(CGSizeZero, self.calculatedSize), @"self.calculatedSize can not be zero. Make sure that you are setting a preferredFrameSize or wrapping ASMapNode in a ASRatioLayoutSpec or similar.");
_options.size = self.calculatedSize;
_snapshotter = [[MKMapSnapshotter alloc] initWithOptions:_options];
}
}
#pragma mark - Action
- (void)resetSnapshotter
{
if (!_snapshotter.isLoading) {
_snapshotter = [[MKMapSnapshotter alloc] initWithOptions:_options];
}
}
#pragma mark - Actions
- (void)addLiveMap
{
if (self.isNodeLoaded && !_mapNode) {
_mapNode = [[ASDisplayNode alloc]initWithViewBlock:^UIView *{
_mapView = [[MKMapView alloc]initWithFrame:CGRectMake(0.0f, 0.0f, self.calculatedSize.width, self.calculatedSize.height)];
_mapView.delegate = _mapDelegate;
[_mapView setRegion:_options.region];
[_mapView addAnnotations:_annotations];
return _mapView;
}];
[self addSubnode:_mapNode];
ASDisplayNodeAssertMainThread();
if (!self.isLiveMap) {
__weak ASMapNode *weakSelf = self;
_mapView = [[MKMapView alloc] initWithFrame:CGRectZero];
_mapView.delegate = weakSelf.mapDelegate;
[_mapView setRegion:_options.region];
[_mapView addAnnotations:_annotations];
[weakSelf setNeedsLayout];
[weakSelf.view addSubview:_mapView];
if (CLLocationCoordinate2DIsValid(_centerCoordinateOfMap)) {
[_mapView setCenterCoordinate:_centerCoordinateOfMap];
} else {
_centerCoordinateOfMap = _options.region.center;
}
}
}
- (void)removeLiveMap
{
if (_mapNode) {
_centerCoordinateOfMap = _mapView.centerCoordinate;
[_mapNode removeFromSupernode];
_mapView = nil;
_mapNode = nil;
_centerCoordinateOfMap = _mapView.centerCoordinate;
[_mapView removeFromSuperview];
_mapView = nil;
}
- (void)setAnnotations:(NSArray *)annotations
{
ASDN::MutexLocker l(_propertyLock);
_annotations = [annotations copy];
if (self.isLiveMap) {
[_mapView removeAnnotations:_mapView.annotations];
[_mapView addAnnotations:annotations];
} else {
[self takeSnapshot];
}
self.image = nil;
}
#pragma mark - Layout
@ -193,18 +224,15 @@
- (void)layout
{
[super layout];
if (_mapView) {
if (self.isLiveMap) {
_mapView.frame = CGRectMake(0.0f, 0.0f, self.calculatedSize.width, self.calculatedSize.height);
}
else {
} else {
// If our bounds.size is different from our current snapshot size, then let's request a new image from MKMapSnapshotter.
if (!CGSizeEqualToSize(_options.size, self.bounds.size)) {
if (_needsMapReloadOnBoundsChange && self.image) {
[self resetSnapshotter];
[self takeSnapshot];
}
if (!CGSizeEqualToSize(_options.size, self.bounds.size) && _needsMapReloadOnBoundsChange) {
_options.size = self.bounds.size;
[self resetSnapshotter];
[self takeSnapshot];
}
}
}
@end
@end

View File

@ -0,0 +1,29 @@
//
// ASPagerNode.h
// AsyncDisplayKit
//
// Created by Levi McCallum on 12/7/15.
// Copyright © 2015 Facebook. All rights reserved.
//
#import <AsyncDisplayKit/ASCollectionNode.h>
@protocol ASPagerNodeDataSource;
@interface ASPagerNode : ASCollectionNode
@property (weak, nonatomic) id<ASPagerNodeDataSource> dataSource;
- (void)reloadData;
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType;
@end
@protocol ASPagerNodeDataSource <NSObject>
- (NSInteger)numberOfPagesInPagerNode:(ASPagerNode *)pagerNode;
- (ASCellNode *)pagerNode:(ASPagerNode *)pagerNode nodeAtIndex:(NSInteger)index;
@end

View File

@ -0,0 +1,74 @@
//
// ASPagerNode.m
// AsyncDisplayKit
//
// Created by Levi McCallum on 12/7/15.
// Copyright © 2015 Facebook. All rights reserved.
//
#import "ASPagerNode.h"
#import <AsyncDisplayKit/AsyncDisplayKit.h>
@interface ASPagerNode () <ASCollectionViewDataSource, ASCollectionViewDelegateFlowLayout> {
UICollectionViewFlowLayout *_flowLayout;
}
@end
@implementation ASPagerNode
- (instancetype)init
{
_flowLayout = [[UICollectionViewFlowLayout alloc] init];
_flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
_flowLayout.minimumInteritemSpacing = 0;
_flowLayout.minimumLineSpacing = 0;
self = [super initWithCollectionViewLayout:_flowLayout];
if (self != nil) {
self.view.asyncDataSource = self;
self.view.asyncDelegate = self;
self.view.pagingEnabled = YES;
self.view.allowsSelection = NO;
self.view.showsVerticalScrollIndicator = NO;
self.view.showsHorizontalScrollIndicator = NO;
ASRangeTuningParameters tuningParams = { .leadingBufferScreenfuls = 1.0, .trailingBufferScreenfuls = 1.0 };
[self setTuningParameters:tuningParams forRangeType:ASLayoutRangeTypePreload];
[self setTuningParameters:tuningParams forRangeType:ASLayoutRangeTypeRender];
}
return self;
}
- (void)reloadData
{
[self.view reloadData];
}
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType
{
[self.view setTuningParameters:tuningParameters forRangeType:rangeType];
}
#pragma mark - ASCollectionViewDataSource
- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForItemAtIndexPath:(NSIndexPath *)indexPath
{
ASDisplayNodeAssert(self.dataSource != nil, @"ASPagerNode must have a data source to load paging nodes");
return [self.dataSource pagerNode:self nodeAtIndex:indexPath.item];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
ASDisplayNodeAssert(self.dataSource != nil, @"ASPagerNode must have a data source to load paging nodes");
return [self.dataSource numberOfPagesInPagerNode:self];
}
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath
{
return ASSizeRangeMake(CGSizeZero, self.view.bounds.size);
}
@end

View File

@ -194,6 +194,9 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) {
/**
@abstract Responds to actions from links in the text node.
@discussion The delegate must be set before the node is loaded, and implement
textNode:longPressedLinkAttribute:value:atPoint:textRange: in order for
the long press gesture recognizer to be installed.
*/
@property (nonatomic, weak) id<ASTextNodeDelegate> delegate;
@ -233,6 +236,8 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) {
@param value The value of the tapped attribute.
@param point The point within textNode, in textNode's coordinate system, that was tapped.
@param textRange The range of highlighted text.
@discussion In addition to implementing this method, the delegate must be set on the text
node before it is loaded (the recognizer is created in -didLoad)
*/
- (void)textNode:(ASTextNode *)textNode longPressedLinkAttribute:(NSString *)attribute value:(id)value atPoint:(CGPoint)point textRange:(NSRange)textRange;

View File

@ -23,6 +23,7 @@
#import "ASInternalHelpers.h"
#import "ASEqualityHelpers.h"
#import "ASLayout.h"
static const NSTimeInterval ASTextNodeHighlightFadeOutDuration = 0.15;
static const NSTimeInterval ASTextNodeHighlightFadeInDuration = 0.1;
@ -211,8 +212,9 @@ static NSString *ASTextNodeTruncationTokenAttributeName = @"ASTextNodeTruncation
{
[super didLoad];
// If we are view-backed, support gesture interaction.
if (!self.isLayerBacked) {
// If we are view-backed and the delegate cares, support the long-press callback.
SEL longPressCallback = @selector(textNode:longPressedLinkAttribute:value:atPoint:textRange:);
if (!self.isLayerBacked && [self.delegate respondsToSelector:longPressCallback]) {
_longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(_handleLongPress:)];
_longPressGestureRecognizer.cancelsTouchesInView = self.longPressCancelsTouches;
_longPressGestureRecognizer.delegate = self;
@ -289,7 +291,29 @@ static NSString *ASTextNodeTruncationTokenAttributeName = @"ASTextNodeTruncation
- (BOOL)_needInvalidateRenderer:(CGSize)newSize
{
return !CGSizeEqualToSize(newSize, _constrainedSize);
if (!_renderer) {
return YES;
}
// If the size is not the same as the constraint we provided to the renderer, start out assuming we need
// a new one. However, there are common cases where the constrained size doesn't need to be the same as calculated.
CGSize oldSize = _renderer.constrainedSize;
if (CGSizeEqualToSize(newSize, oldSize)) {
return NO;
} else {
// It is very common to have a constrainedSize with a concrete, specific width but +Inf height.
// In this case, as long as the text node has bounds as large as the full calculatedLayout suggests,
// it means that the text has all the room it needs (as it was not vertically bounded). So, we will not
// experience truncation and don't need to recreate the renderer with the size it already calculated,
// as this would essentially serve to set its constrainedSize to be its calculatedSize (unnecessary).
ASLayout *layout = self.calculatedLayout;
if (layout != nil && CGSizeEqualToSize(newSize, layout.size)) {
return NO;
} else {
return YES;
}
}
}
#pragma mark - Modifying User Text
@ -305,6 +329,11 @@ static NSString *ASTextNodeTruncationTokenAttributeName = @"ASTextNodeTruncation
_attributedString = ASCleanseAttributedStringOfCoreTextAttributes(attributedString);
// Sync the truncation string with attributes from the updated _attributedString
// Without this, the size calculation of the text with truncation applied will
// not take into account the attributes of attributedString in the last line
[self _updateComposedTruncationString];
// We need an entirely new renderer
[self _invalidateRenderer];
@ -1024,9 +1053,14 @@ static NSAttributedString *DefaultTruncationAttributedString()
#pragma mark - Truncation Message
- (void)_invalidateTruncationString
- (void)_updateComposedTruncationString
{
_composedTruncationString = [self _prepareTruncationStringForDrawing:[self _composedTruncationString]];
}
- (void)_invalidateTruncationString
{
[self _updateComposedTruncationString];
[self _invalidateRenderer];
ASDisplayNodeRespectThreadAffinityOfNode(self, ^{
[self setNeedsDisplay];

View File

@ -30,6 +30,8 @@
#import <AsyncDisplayKit/ASScrollNode.h>
#import <AsyncDisplayKit/ASPagerNode.h>
#import <AsyncDisplayKit/ASViewController.h>
#import <AsyncDisplayKit/ASChangeSetDataController.h>

View File

@ -57,7 +57,7 @@ CGFloat ASRelativeDimensionResolve(ASRelativeDimension dimension, CGFloat parent
case ASRelativeDimensionTypePoints:
return dimension.value;
case ASRelativeDimensionTypePercent:
return round(dimension.value * parent);
return dimension.value * parent;
}
}

View File

@ -11,6 +11,7 @@
#import "ASLayout.h"
#import "ASAssert.h"
#import "ASLayoutSpecUtilities.h"
#import "ASInternalHelpers.h"
#import <stack>
CGPoint const CGPointNull = {NAN, NAN};
@ -37,8 +38,12 @@ extern BOOL CGPointIsNull(CGPoint point)
ASLayout *l = [super new];
if (l) {
l->_layoutableObject = layoutableObject;
l->_size = size;
l->_position = position;
l->_size = CGSizeMake(ASCeilPixelValue(size.width), ASCeilPixelValue(size.height));
if (CGPointIsNull(position) == NO) {
l->_position = CGPointMake(ASCeilPixelValue(position.x), ASCeilPixelValue(position.y));
} else {
l->_position = position;
}
l->_sublayouts = [sublayouts copy];
}
return l;

View File

@ -88,7 +88,7 @@ NSDictionary *NSAttributedStringAttributesForCoreTextAttributes(NSDictionary *co
cleanAttributes[NSForegroundColorAttributeName] = [UIColor colorWithCGColor:(CGColorRef)coreTextValue];
}
// kCTParagraphStyleAttributeName -> NSParagraphStyleAttributeName
else if ([coreTextKey isEqualToString:(NSString *)kCTParagraphStyleAttributeName]) {
else if ([coreTextKey isEqualToString:(NSString *)kCTParagraphStyleAttributeName] && ![coreTextValue isKindOfClass:[NSParagraphStyle class]]) {
cleanAttributes[NSParagraphStyleAttributeName] = [NSParagraphStyle paragraphStyleWithCTParagraphStyle:(CTParagraphStyleRef)coreTextValue];
}
// kCTStrokeWidthAttributeName -> NSStrokeWidthAttributeName

View File

@ -62,6 +62,7 @@
effectiveRange:NULL];
NSParagraphStyle *paragraphStyle = [textStorage attributesAtIndex:[layoutManager characterIndexForGlyphAtIndex:lastVisibleGlyphIndex]
effectiveRange:NULL][NSParagraphStyleAttributeName];
// We assume LTR so long as the writing direction is not
BOOL rtlWritingDirection = paragraphStyle ? paragraphStyle.baseWritingDirection == NSWritingDirectionRightToLeft : NO;
// We only want to treat the trunction rect as left-aligned in the case that we are right-aligned and our writing

View File

@ -36,11 +36,11 @@ static CALayer *layerWithName(NSString *name) {
}
static NSString *orderStringFromSublayers(CALayer *l) {
return [[l.sublayers valueForKey:@"name"] componentsJoinedByString:@","];
return [[[l.sublayers valueForKey:@"asyncdisplaykit_node"] valueForKey:@"name"] componentsJoinedByString:@","];
}
static NSString *orderStringFromSubviews(UIView *v) {
return [[v.subviews valueForKey:@"name"] componentsJoinedByString:@","];
return [[[v.subviews valueForKey:@"asyncdisplaykit_node"] valueForKey:@"name"] componentsJoinedByString:@","];
}
static NSString *orderStringFromSubnodes(ASDisplayNode *n) {

View File

@ -12,6 +12,11 @@
#import "ASTextKitCoreTextAdditions.h"
BOOL floatsCloseEnough(CGFloat float1, CGFloat float2) {
CGFloat epsilon = 0.00001;
return (fabs(float1 - float2) < epsilon);
}
@interface ASTextKitCoreTextAdditionsTests : XCTestCase
@end
@ -44,5 +49,21 @@
XCTAssertTrue([testString isEqualToAttributedString:actualCleansedString], @"Expected the output string %@ to be the same as the input %@ if there are no core text attributes", actualCleansedString, testString);
}
- (void)testNSParagraphStyleNoCleansing
{
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = 10.0;
//NSUnderlineStyleAttributeName flags the unsupported CT attribute check
NSDictionary *attributes = @{NSParagraphStyleAttributeName:paragraphStyle,
NSUnderlineStyleAttributeName:@(NSUnderlineStyleSingle)};
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:@"Test" attributes:attributes];
NSAttributedString *cleansedString = ASCleanseAttributedStringOfCoreTextAttributes(attributedString);
NSParagraphStyle *cleansedParagraphStyle = [cleansedString attribute:NSParagraphStyleAttributeName atIndex:0 effectiveRange:NULL];
XCTAssertTrue(floatsCloseEnough(cleansedParagraphStyle.lineSpacing, paragraphStyle.lineSpacing), @"Expected the output line spacing: %f to be equal to the input line spacing: %f", cleansedParagraphStyle.lineSpacing, paragraphStyle.lineSpacing);
}
@end

View File

@ -54,7 +54,7 @@ static BOOL CGSizeEqualToSizeWithIn(CGSize size1, CGSize size2, CGFloat delta)
{
[super setUp];
_textNode = [[ASTextNode alloc] init];
UIFontDescriptor *desc =
[UIFontDescriptor fontDescriptorWithName:@"Didot" size:18];
NSArray *arr =
@ -69,7 +69,17 @@ static BOOL CGSizeEqualToSizeWithIn(CGSize size1, CGSize size2, CGFloat delta)
[[NSMutableAttributedString alloc] initWithString:@"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." attributes:d];
NSMutableParagraphStyle *para = [NSMutableParagraphStyle new];
para.alignment = NSTextAlignmentCenter;
[mas addAttribute:NSParagraphStyleAttributeName value:para range:NSMakeRange(0,mas.length)];
para.lineSpacing = 1.0;
[mas addAttribute:NSParagraphStyleAttributeName value:para
range:NSMakeRange(0, mas.length - 1)];
// Vary the linespacing on the last line
NSMutableParagraphStyle *lastLinePara = [NSMutableParagraphStyle new];
lastLinePara.alignment = para.alignment;
lastLinePara.lineSpacing = 5.0;
[mas addAttribute:NSParagraphStyleAttributeName value:lastLinePara
range:NSMakeRange(mas.length - 1, 1)];
_attributedString = mas;
_textNode.attributedString = _attributedString;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

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

View File

@ -0,0 +1,374 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
0585428019D4DBE100606EA6 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0585427F19D4DBE100606EA6 /* Default-568h@2x.png */; };
05E2128719D4DB510098F589 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 05E2128619D4DB510098F589 /* main.m */; };
05E2128A19D4DB510098F589 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 05E2128919D4DB510098F589 /* AppDelegate.m */; };
05E2128D19D4DB510098F589 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 05E2128C19D4DB510098F589 /* ViewController.m */; };
252041E21C167DFC00E264C8 /* PageNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 252041E11C167DFC00E264C8 /* PageNode.m */; };
3EC0CDCBA10D483D9F386E5E /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D24B17D1E4A4E7A9566C5E9 /* libPods.a */; };
6C2C82AC19EE274300767484 /* Default-667h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6C2C82AA19EE274300767484 /* Default-667h@2x.png */; };
6C2C82AD19EE274300767484 /* Default-736h@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6C2C82AB19EE274300767484 /* Default-736h@3x.png */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
0585427F19D4DBE100606EA6 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "../Default-568h@2x.png"; sourceTree = "<group>"; };
05E2128119D4DB510098F589 /* Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample.app; sourceTree = BUILT_PRODUCTS_DIR; };
05E2128519D4DB510098F589 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
05E2128619D4DB510098F589 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
05E2128819D4DB510098F589 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
05E2128919D4DB510098F589 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
05E2128B19D4DB510098F589 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
05E2128C19D4DB510098F589 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
088AA6578212BE9BFBB07B70 /* 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>"; };
252041E01C167DFC00E264C8 /* PageNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageNode.h; sourceTree = "<group>"; };
252041E11C167DFC00E264C8 /* PageNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PageNode.m; sourceTree = "<group>"; };
3D24B17D1E4A4E7A9566C5E9 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
6C2C82AA19EE274300767484 /* Default-667h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-667h@2x.png"; sourceTree = SOURCE_ROOT; };
6C2C82AB19EE274300767484 /* Default-736h@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-736h@3x.png"; sourceTree = SOURCE_ROOT; };
C068F1D3F0CC317E895FCDAB /* 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>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
05E2127E19D4DB510098F589 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
3EC0CDCBA10D483D9F386E5E /* libPods.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
05E2127819D4DB510098F589 = {
isa = PBXGroup;
children = (
05E2128319D4DB510098F589 /* Sample */,
05E2128219D4DB510098F589 /* Products */,
1A943BF0259746F18D6E423F /* Frameworks */,
1AE410B73DA5C3BD087ACDD7 /* Pods */,
);
indentWidth = 2;
sourceTree = "<group>";
tabWidth = 2;
usesTabs = 0;
};
05E2128219D4DB510098F589 /* Products */ = {
isa = PBXGroup;
children = (
05E2128119D4DB510098F589 /* Sample.app */,
);
name = Products;
sourceTree = "<group>";
};
05E2128319D4DB510098F589 /* Sample */ = {
isa = PBXGroup;
children = (
252041E01C167DFC00E264C8 /* PageNode.h */,
252041E11C167DFC00E264C8 /* PageNode.m */,
05E2128819D4DB510098F589 /* AppDelegate.h */,
05E2128919D4DB510098F589 /* AppDelegate.m */,
05E2128B19D4DB510098F589 /* ViewController.h */,
05E2128C19D4DB510098F589 /* ViewController.m */,
05E2128419D4DB510098F589 /* Supporting Files */,
);
path = Sample;
sourceTree = "<group>";
};
05E2128419D4DB510098F589 /* Supporting Files */ = {
isa = PBXGroup;
children = (
0585427F19D4DBE100606EA6 /* Default-568h@2x.png */,
6C2C82AA19EE274300767484 /* Default-667h@2x.png */,
6C2C82AB19EE274300767484 /* Default-736h@3x.png */,
05E2128519D4DB510098F589 /* Info.plist */,
05E2128619D4DB510098F589 /* main.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
1A943BF0259746F18D6E423F /* Frameworks */ = {
isa = PBXGroup;
children = (
3D24B17D1E4A4E7A9566C5E9 /* libPods.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
1AE410B73DA5C3BD087ACDD7 /* Pods */ = {
isa = PBXGroup;
children = (
C068F1D3F0CC317E895FCDAB /* Pods.debug.xcconfig */,
088AA6578212BE9BFBB07B70 /* Pods.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
05E2128019D4DB510098F589 /* Sample */ = {
isa = PBXNativeTarget;
buildConfigurationList = 05E212A419D4DB510098F589 /* Build configuration list for PBXNativeTarget "Sample" */;
buildPhases = (
E080B80F89C34A25B3488E26 /* Check Pods Manifest.lock */,
05E2127D19D4DB510098F589 /* Sources */,
05E2127E19D4DB510098F589 /* Frameworks */,
05E2127F19D4DB510098F589 /* Resources */,
F012A6F39E0149F18F564F50 /* Copy Pods Resources */,
D668455448B2FFAC9BEF28DD /* Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = Sample;
productName = Sample;
productReference = 05E2128119D4DB510098F589 /* Sample.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
05E2127919D4DB510098F589 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0710;
ORGANIZATIONNAME = Facebook;
TargetAttributes = {
05E2128019D4DB510098F589 = {
CreatedOnToolsVersion = 6.0.1;
};
};
};
buildConfigurationList = 05E2127C19D4DB510098F589 /* Build configuration list for PBXProject "Sample" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 05E2127819D4DB510098F589;
productRefGroup = 05E2128219D4DB510098F589 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
05E2128019D4DB510098F589 /* Sample */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
05E2127F19D4DB510098F589 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0585428019D4DBE100606EA6 /* Default-568h@2x.png in Resources */,
6C2C82AC19EE274300767484 /* Default-667h@2x.png in Resources */,
6C2C82AD19EE274300767484 /* Default-736h@3x.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
D668455448B2FFAC9BEF28DD /* Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
E080B80F89C34A25B3488E26 /* 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;
};
F012A6F39E0149F18F564F50 /* 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;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
05E2127D19D4DB510098F589 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
05E2128D19D4DB510098F589 /* ViewController.m in Sources */,
05E2128A19D4DB510098F589 /* AppDelegate.m in Sources */,
05E2128719D4DB510098F589 /* main.m in Sources */,
252041E21C167DFC00E264C8 /* PageNode.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
05E212A219D4DB510098F589 /* 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;
ENABLE_TESTABILITY = 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.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
05E212A319D4DB510098F589 /* 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.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
05E212A519D4DB510098F589 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = C068F1D3F0CC317E895FCDAB /* Pods.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = Sample/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.AsyncDisplayKit.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
05E212A619D4DB510098F589 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 088AA6578212BE9BFBB07B70 /* Pods.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = Sample/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.AsyncDisplayKit.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
05E2127C19D4DB510098F589 /* Build configuration list for PBXProject "Sample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
05E212A219D4DB510098F589 /* Debug */,
05E212A319D4DB510098F589 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
05E212A419D4DB510098F589 /* Build configuration list for PBXNativeTarget "Sample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
05E212A519D4DB510098F589 /* Debug */,
05E212A619D4DB510098F589 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 05E2127919D4DB510098F589 /* Project object */;
}

View File

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

View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0710"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "05E2128019D4DB510098F589"
BuildableName = "Sample.app"
BlueprintName = "Sample"
ReferencedContainer = "container:Sample.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "05E2128019D4DB510098F589"
BuildableName = "Sample.app"
BlueprintName = "Sample"
ReferencedContainer = "container:Sample.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "05E2128019D4DB510098F589"
BuildableName = "Sample.app"
BlueprintName = "Sample"
ReferencedContainer = "container:Sample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "05E2128019D4DB510098F589"
BuildableName = "Sample.app"
BlueprintName = "Sample"
ReferencedContainer = "container:Sample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

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

View File

@ -0,0 +1,18 @@
/* 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 AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end

View File

@ -0,0 +1,27 @@
/* 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 = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
[self.window makeKeyAndVisible];
return YES;
}
@end

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</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>
</dict>
</plist>

View File

@ -0,0 +1,13 @@
//
// PageNode.h
// Sample
//
// Created by McCallum, Levi on 12/7/15.
// Copyright © 2015 Facebook. All rights reserved.
//
#import <AsyncDisplayKit/AsyncDisplayKit.h>
@interface PageNode : ASCellNode
@end

View File

@ -0,0 +1,24 @@
//
// PageNode.m
// Sample
//
// Created by McCallum, Levi on 12/7/15.
// Copyright © 2015 Facebook. All rights reserved.
//
#import "PageNode.h"
@implementation PageNode
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
{
return [ASLayout layoutWithLayoutableObject:self size:constrainedSize.max];
}
- (void)fetchData
{
[super fetchData];
NSLog(@"Fetching data for node: %@", self);
}
@end

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 <AsyncDisplayKit/AsyncDisplayKit.h>
@interface ViewController : ASViewController
@end

View File

@ -0,0 +1,57 @@
/* 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>
#import "PageNode.h"
@interface ViewController () <ASPagerNodeDataSource>
- (ASPagerNode *)node;
@end
@implementation ViewController
- (instancetype)init
{
if (!(self = [super initWithNode:[[ASPagerNode alloc] init]]))
return nil;
[self node].dataSource = self;
self.title = @"Pages";
return self;
}
- (ASPagerNode *)node
{
return (ASPagerNode *)[super node];
}
#pragma mark - ASPagerNodeDataSource
- (NSInteger)numberOfPagesInPagerNode:(ASPagerNode *)pagerNode
{
return 5;
}
- (ASCellNode *)pagerNode:(ASPagerNode *)pagerNode nodeAtIndex:(NSInteger)index
{
PageNode *page = [[PageNode alloc] init];
page.backgroundColor = [UIColor blueColor];
return page;
}
@end

View File

@ -0,0 +1,20 @@
/* 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>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}