diff --git a/examples/ASCollectionView/Sample/PresentingViewController.m b/examples/ASCollectionView/Sample/PresentingViewController.m index 49c65e6906..80669f29b8 100644 --- a/examples/ASCollectionView/Sample/PresentingViewController.m +++ b/examples/ASCollectionView/Sample/PresentingViewController.m @@ -18,6 +18,7 @@ - (void)viewDidLoad { [super viewDidLoad]; + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Push Details" style:UIBarButtonItemStylePlain target:self action:@selector(pushNewViewController)]; } diff --git a/examples/ASCollectionView/Sample/SupplementaryNode.m b/examples/ASCollectionView/Sample/SupplementaryNode.m index ca5579e9a6..96e07195b0 100644 --- a/examples/ASCollectionView/Sample/SupplementaryNode.m +++ b/examples/ASCollectionView/Sample/SupplementaryNode.m @@ -17,9 +17,11 @@ static CGFloat kInsets = 15.0; -@implementation SupplementaryNode { - ASTextNode *_textNode; -} +@interface SupplementaryNode () +@property (nonatomic, strong) ASTextNode *textNode; +@end + +@implementation SupplementaryNode - (instancetype)initWithText:(NSString *)text { @@ -37,7 +39,7 @@ static CGFloat kInsets = 15.0; { ASCenterLayoutSpec *center = [[ASCenterLayoutSpec alloc] init]; center.centeringOptions = ASCenterLayoutSpecCenteringXY; - center.child = _textNode; + center.child = self.textNode; UIEdgeInsets insets = UIEdgeInsetsMake(kInsets, kInsets, kInsets, kInsets); return [ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:center]; } @@ -47,9 +49,9 @@ static CGFloat kInsets = 15.0; - (NSDictionary *)textAttributes { return @{ - NSFontAttributeName: [UIFont systemFontOfSize:18.0], - NSForegroundColorAttributeName: [UIColor whiteColor], - }; + NSFontAttributeName: [UIFont systemFontOfSize:18.0], + NSForegroundColorAttributeName: [UIColor whiteColor], + }; } @end diff --git a/examples/ASCollectionView/Sample/ViewController.m b/examples/ASCollectionView/Sample/ViewController.m index 00aea567dc..7286703e90 100644 --- a/examples/ASCollectionView/Sample/ViewController.m +++ b/examples/ASCollectionView/Sample/ViewController.m @@ -15,50 +15,48 @@ #import "SupplementaryNode.h" #import "ItemNode.h" +@interface ViewController () +@property (nonatomic, strong) ASCollectionView *collectionView; +@property (nonatomic, strong) NSArray *data; +@end + @interface ViewController () -{ - ASCollectionView *_collectionView; - NSArray *_data; -} @end @implementation ViewController -#pragma mark - -#pragma mark UIViewController. - -- (instancetype)init +- (void)dealloc { - if (!(self = [super init])) - return nil; + self.collectionView.asyncDataSource = nil; + self.collectionView.asyncDelegate = nil; - UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; - layout.headerReferenceSize = CGSizeMake(50.0, 50.0); - layout.footerReferenceSize = CGSizeMake(50.0, 50.0); - - _collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; - _collectionView.asyncDataSource = self; - _collectionView.asyncDelegate = self; - _collectionView.backgroundColor = [UIColor whiteColor]; - - [_collectionView registerSupplementaryNodeOfKind:UICollectionElementKindSectionHeader]; - [_collectionView registerSupplementaryNodeOfKind:UICollectionElementKindSectionFooter]; - -#if !SIMULATE_WEB_RESPONSE - self.navigationItem.leftItemsSupplementBackButton = YES; - self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(reloadTapped)]; -#endif - - return self; + NSLog(@"ViewController is deallocing"); } - (void)viewDidLoad { [super viewDidLoad]; - [self.view addSubview:_collectionView]; + UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + layout.headerReferenceSize = CGSizeMake(50.0, 50.0); + layout.footerReferenceSize = CGSizeMake(50.0, 50.0); + + self.collectionView = [[ASCollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout]; + self.collectionView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + self.collectionView.asyncDataSource = self; + self.collectionView.asyncDelegate = self; + self.collectionView.backgroundColor = [UIColor whiteColor]; + + [self.collectionView registerSupplementaryNodeOfKind:UICollectionElementKindSectionHeader]; + [self.collectionView registerSupplementaryNodeOfKind:UICollectionElementKindSectionFooter]; + [self.view addSubview:self.collectionView]; + +#if !SIMULATE_WEB_RESPONSE + self.navigationItem.leftItemsSupplementBackButton = YES; + self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(reloadTapped)]; +#endif #if SIMULATE_WEB_RESPONSE __weak typeof(self) weakSelf = self; @@ -86,11 +84,6 @@ #endif } -- (void)viewWillLayoutSubviews -{ - _collectionView.frame = self.view.bounds; -} - - (BOOL)prefersStatusBarHidden { return YES; @@ -98,27 +91,26 @@ - (void)reloadTapped { - [_collectionView reloadData]; + [self.collectionView reloadData]; } #pragma mark - #pragma mark ASCollectionView data source. -- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForItemAtIndexPath:(NSIndexPath *)indexPath +- (ASCellNodeBlock)collectionView:(ASCollectionView *)collectionView nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath; { NSString *text = [NSString stringWithFormat:@"[%zd.%zd] says hi", indexPath.section, indexPath.item]; - return [[ItemNode alloc] initWithString:text]; + return ^{ + return [[ItemNode alloc] initWithString:text]; + }; } - (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { NSString *text = [kind isEqualToString:UICollectionElementKindSectionHeader] ? @"Header" : @"Footer"; SupplementaryNode *node = [[SupplementaryNode alloc] initWithText:text]; - if ([kind isEqualToString:UICollectionElementKindSectionHeader]) { - node.backgroundColor = [UIColor blueColor]; - } else { - node.backgroundColor = [UIColor redColor]; - } + BOOL isHeaderSection = [kind isEqualToString:UICollectionElementKindSectionHeader]; + node.backgroundColor = isHeaderSection ? [UIColor blueColor] : [UIColor redColor]; return node; } @@ -153,15 +145,9 @@ [context completeBatchFetching:YES]; } -- (UIEdgeInsets)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { +- (UIEdgeInsets)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section +{ return UIEdgeInsetsMake(20.0, 20.0, 20.0, 20.0); } -#if SIMULATE_WEB_RESPONSE --(void)dealloc -{ - NSLog(@"ViewController is deallocing"); -} -#endif - @end diff --git a/examples/CatDealsCollectionView/Sample/ViewController.m b/examples/CatDealsCollectionView/Sample/ViewController.m index 31a1e35435..da2a271a40 100644 --- a/examples/CatDealsCollectionView/Sample/ViewController.m +++ b/examples/CatDealsCollectionView/Sample/ViewController.m @@ -159,10 +159,12 @@ static const CGFloat kVerticalSectionPadding = 20.0f; #pragma mark - #pragma mark ASCollectionView data source. -- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForItemAtIndexPath:(NSIndexPath *)indexPath +- (ASCellNodeBlock)collectionView:(ASCollectionView *)collectionView nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath { ItemViewModel *viewModel = _data[indexPath.item]; - return [[ItemNode alloc] initWithViewModel:viewModel]; + return ^{ + return [[ItemNode alloc] initWithViewModel:viewModel]; + }; } - (ASCellNode *)collectionView:(UICollectionView *)collectionView nodeForSupplementaryElementOfKind:(nonnull NSString *)kind atIndexPath:(nonnull NSIndexPath *)indexPath { diff --git a/examples/CollectionViewWithViewControllerCells/Sample/ViewController.m b/examples/CollectionViewWithViewControllerCells/Sample/ViewController.m index 36f0ef5011..6353bc61e2 100644 --- a/examples/CollectionViewWithViewControllerCells/Sample/ViewController.m +++ b/examples/CollectionViewWithViewControllerCells/Sample/ViewController.m @@ -34,34 +34,21 @@ static NSUInteger kNumberOfImages = 14; - (instancetype)init { - if (!(self = [super init])) - return nil; - - _sections = [NSMutableArray array]; - [_sections addObject:[NSMutableArray array]]; - for (NSUInteger idx = 0, section = 0; idx < kNumberOfImages; idx++) { - NSString *name = [NSString stringWithFormat:@"image_%lu.jpg", (unsigned long)idx]; - [_sections[section] addObject:[UIImage imageNamed:name]]; - if ((idx + 1) % 5 == 0 && idx < kNumberOfImages - 1) { - section++; - [_sections addObject:[NSMutableArray array]]; + self = [super init]; + if (self) { + + _sections = [NSMutableArray array]; + [_sections addObject:[NSMutableArray array]]; + for (NSUInteger idx = 0, section = 0; idx < kNumberOfImages; idx++) { + NSString *name = [NSString stringWithFormat:@"image_%lu.jpg", (unsigned long)idx]; + [_sections[section] addObject:[UIImage imageNamed:name]]; + if ((idx + 1) % 5 == 0 && idx < kNumberOfImages - 1) { + section++; + [_sections addObject:[NSMutableArray array]]; + } } + } - - MosaicCollectionViewLayout *layout = [[MosaicCollectionViewLayout alloc] init]; - layout.numberOfColumns = 2; - layout.headerHeight = 44.0; - - _layoutInspector = [[MosaicCollectionViewLayoutInspector alloc] init]; - - _collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout asyncDataFetching:YES]; - _collectionView.asyncDataSource = self; - _collectionView.asyncDelegate = self; - _collectionView.layoutInspector = _layoutInspector; - _collectionView.backgroundColor = [UIColor whiteColor]; - - [_collectionView registerSupplementaryNodeOfKind:UICollectionElementKindSectionHeader]; - return self; } @@ -69,12 +56,27 @@ static NSUInteger kNumberOfImages = 14; { [super viewDidLoad]; + MosaicCollectionViewLayout *layout = [[MosaicCollectionViewLayout alloc] init]; + layout.numberOfColumns = 2; + layout.headerHeight = 44.0; + + _layoutInspector = [[MosaicCollectionViewLayoutInspector alloc] init]; + + _collectionView = [[ASCollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout]; + _collectionView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + _collectionView.asyncDataSource = self; + _collectionView.asyncDelegate = self; + _collectionView.layoutInspector = _layoutInspector; + _collectionView.backgroundColor = [UIColor whiteColor]; + + [_collectionView registerSupplementaryNodeOfKind:UICollectionElementKindSectionHeader]; [self.view addSubview:_collectionView]; } -- (void)viewWillLayoutSubviews +- (void)dealloc { - _collectionView.frame = self.view.bounds; + _collectionView.asyncDataSource = nil; + _collectionView.asyncDelegate = nil; } - (BOOL)prefersStatusBarHidden @@ -90,16 +92,17 @@ static NSUInteger kNumberOfImages = 14; #pragma mark - #pragma mark ASCollectionView data source. -- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForItemAtIndexPath:(NSIndexPath *)indexPath +- (ASCellNodeBlock)collectionView:(ASCollectionView *)collectionView nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath { - ASCellNode *node = [[ASCellNode alloc] initWithViewControllerBlock:^UIViewController *{ - return [[ImageViewController alloc] initWithImage:_sections[indexPath.section][indexPath.item]]; - } didLoadBlock:nil]; - - node.layer.borderWidth = 1.0; - node.layer.borderColor = [UIColor blackColor].CGColor; - - return node; + UIImage *image = _sections[indexPath.section][indexPath.item]; + return ^{ + return [[ASCellNode alloc] initWithViewControllerBlock:^UIViewController *{ + return [[ImageViewController alloc] initWithImage:image]; + } didLoadBlock:^(ASDisplayNode * _Nonnull node) { + node.layer.borderWidth = 1.0; + node.layer.borderColor = [UIColor blackColor].CGColor; + }]; + }; } - (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath @@ -108,11 +111,13 @@ static NSUInteger kNumberOfImages = 14; return [[SupplementaryNode alloc] initWithText:text]; } -- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { +- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView +{ return _sections.count; } -- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section +{ return [_sections[section] count]; } diff --git a/examples/CustomCollectionView/Sample/ImageCellNode.m b/examples/CustomCollectionView/Sample/ImageCellNode.m index 3bb74a142d..02064168c7 100644 --- a/examples/CustomCollectionView/Sample/ImageCellNode.m +++ b/examples/CustomCollectionView/Sample/ImageCellNode.m @@ -31,6 +31,8 @@ - (void)layout { + [super layout]; + _imageNode.frame = CGRectMake(0, 0, _imageNode.calculatedSize.width, _imageNode.calculatedSize.height); } diff --git a/examples/CustomCollectionView/Sample/ViewController.m b/examples/CustomCollectionView/Sample/ViewController.m index f8b6071bad..f919f815fa 100644 --- a/examples/CustomCollectionView/Sample/ViewController.m +++ b/examples/CustomCollectionView/Sample/ViewController.m @@ -65,6 +65,12 @@ static NSUInteger kNumberOfImages = 14; return self; } +- (void)dealloc +{ + _collectionView.asyncDataSource = nil; + _collectionView.asyncDelegate = nil; +} + - (void)viewDidLoad { [super viewDidLoad]; @@ -90,14 +96,18 @@ static NSUInteger kNumberOfImages = 14; #pragma mark - #pragma mark ASCollectionView data source. -- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForItemAtIndexPath:(NSIndexPath *)indexPath +- (ASCellNodeBlock)collectionView:(ASCollectionView *)collectionView nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath { - return [[ImageCellNode alloc] initWithImage:_sections[indexPath.section][indexPath.item]]; + UIImage *image = _sections[indexPath.section][indexPath.item]; + return ^{ + return [[ImageCellNode alloc] initWithImage:image]; + }; } + - (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { - NSString *text = [NSString stringWithFormat:@"Section %d", (int)indexPath.section + 1]; + NSString *text = [NSString stringWithFormat:@"Section %zd", indexPath.section + 1]; return [[SupplementaryNode alloc] initWithText:text]; } diff --git a/examples/HorizontalWithinVerticalScrolling/Sample/HorizontalScrollCellNode.mm b/examples/HorizontalWithinVerticalScrolling/Sample/HorizontalScrollCellNode.mm index 9eb2ee9b31..15b36b8402 100644 --- a/examples/HorizontalWithinVerticalScrolling/Sample/HorizontalScrollCellNode.mm +++ b/examples/HorizontalWithinVerticalScrolling/Sample/HorizontalScrollCellNode.mm @@ -67,11 +67,13 @@ static const CGFloat kInnerPadding = 10.0f; return 5; } -- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForItemAtIndexPath:(NSIndexPath *)indexPath +- (ASCellNodeBlock)collectionView:(ASCollectionView *)collectionView nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath { - RandomCoreGraphicsNode *elementNode = [[RandomCoreGraphicsNode alloc] init]; - elementNode.preferredFrameSize = _elementSize; - return elementNode; + return ^{ + RandomCoreGraphicsNode *elementNode = [[RandomCoreGraphicsNode alloc] init]; + elementNode.preferredFrameSize = _elementSize; + return elementNode; + }; } - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize diff --git a/examples/SocialAppLayout/Sample/CommentsNode.h b/examples/SocialAppLayout/Sample/CommentsNode.h index 5deafb5743..254f6abe2b 100644 --- a/examples/SocialAppLayout/Sample/CommentsNode.h +++ b/examples/SocialAppLayout/Sample/CommentsNode.h @@ -11,14 +11,7 @@ #import -@interface CommentsNode : ASControlNode { - - ASImageNode *_iconNode; - ASTextNode *_countNode; - - NSInteger _comentsCount; - -} +@interface CommentsNode : ASControlNode - (instancetype)initWithCommentsCount:(NSInteger)comentsCount; diff --git a/examples/SocialAppLayout/Sample/CommentsNode.m b/examples/SocialAppLayout/Sample/CommentsNode.m index 97bcc37191..c2f33d1219 100644 --- a/examples/SocialAppLayout/Sample/CommentsNode.m +++ b/examples/SocialAppLayout/Sample/CommentsNode.m @@ -12,32 +12,32 @@ #import "CommentsNode.h" #import "TextStyles.h" +@interface CommentsNode () +@property (nonatomic, strong) ASImageNode *iconNode; +@property (nonatomic, strong) ASTextNode *countNode; +@property (nonatomic, assign) NSInteger commentsCount; +@end + @implementation CommentsNode - (instancetype)initWithCommentsCount:(NSInteger)comentsCount { self = [super init]; - - if(self) { - - _comentsCount = comentsCount; + if (self) { + _commentsCount = comentsCount; _iconNode = [[ASImageNode alloc] init]; _iconNode.image = [UIImage imageNamed:@"icon_comment.png"]; [self addSubnode:_iconNode]; _countNode = [[ASTextNode alloc] init]; - if(_comentsCount > 0) { - - _countNode.attributedString = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%ld", (long)_comentsCount] attributes:[TextStyles cellControlStyle]]; - + if (_commentsCount > 0) { + _countNode.attributedString = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%zd", _commentsCount] attributes:[TextStyles cellControlStyle]]; } - [self addSubnode:_countNode]; // make it tappable easily self.hitTestSlop = UIEdgeInsetsMake(-10, -10, -10, -10); - } return self; @@ -46,18 +46,13 @@ - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize { - ASStackLayoutSpec *mainStack = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal spacing:6.0 justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsCenter children:@[_iconNode, _countNode]]; + ASStackLayoutSpec *mainStack = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal spacing:6.0 justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsCenter children:@[self.iconNode, self.countNode]]; // set sizeRange to make width fixed to 60 - mainStack.sizeRange = ASRelativeSizeRangeMake(ASRelativeSizeMake( - ASRelativeDimensionMakeWithPoints(60.0), - ASRelativeDimensionMakeWithPoints(0.0) - ), ASRelativeSizeMake( - ASRelativeDimensionMakeWithPoints(60.0), - ASRelativeDimensionMakeWithPoints(40.0) - )); + ASRelativeSize min = ASRelativeSizeMake(ASRelativeDimensionMakeWithPoints(60.0), ASRelativeDimensionMakeWithPoints(0.0)); + ASRelativeSize max = ASRelativeSizeMake(ASRelativeDimensionMakeWithPoints(60.0), ASRelativeDimensionMakeWithPoints(40.0)); + mainStack.sizeRange = ASRelativeSizeRangeMake(min,max); return [ASStaticLayoutSpec staticLayoutSpecWithChildren:@[mainStack]]; - } diff --git a/examples/SocialAppLayout/Sample/LikesNode.h b/examples/SocialAppLayout/Sample/LikesNode.h index eb7d778a6c..d294459bc5 100644 --- a/examples/SocialAppLayout/Sample/LikesNode.h +++ b/examples/SocialAppLayout/Sample/LikesNode.h @@ -11,18 +11,8 @@ #import -@interface LikesNode : ASControlNode { - - ASImageNode *_iconNode; - ASTextNode *_countNode; - - NSInteger _likesCount; - BOOL _liked; - -} +@interface LikesNode : ASControlNode - (instancetype)initWithLikesCount:(NSInteger)likesCount; -+ (BOOL) getYesOrNo; - @end diff --git a/examples/SocialAppLayout/Sample/LikesNode.m b/examples/SocialAppLayout/Sample/LikesNode.m index 824fa43a6a..b650398338 100644 --- a/examples/SocialAppLayout/Sample/LikesNode.m +++ b/examples/SocialAppLayout/Sample/LikesNode.m @@ -12,14 +12,19 @@ #import "LikesNode.h" #import "TextStyles.h" -@implementation LikesNode +@interface LikesNode () +@property (nonatomic, strong) ASImageNode *iconNode; +@property (nonatomic, strong) ASTextNode *countNode; +@property (nonatomic, assign) NSInteger likesCount; +@property (nonatomic, assign) BOOL liked; +@end + +@implementation LikesNode - (instancetype)initWithLikesCount:(NSInteger)likesCount { self = [super init]; - - if(self) { - + if (self) { _likesCount = likesCount; _liked = (_likesCount > 0) ? [LikesNode getYesOrNo] : NO; @@ -28,16 +33,12 @@ [self addSubnode:_iconNode]; _countNode = [[ASTextNode alloc] init]; - if(_likesCount > 0) { + if (_likesCount > 0) { - if(_liked) { - _countNode.attributedString = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%ld", (long)_likesCount] attributes:[TextStyles cellControlColoredStyle]]; - }else { - _countNode.attributedString = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%ld", (long)_likesCount] attributes:[TextStyles cellControlStyle]]; - } + NSDictionary *attributes = _liked ? [TextStyles cellControlColoredStyle] : [TextStyles cellControlStyle]; + _countNode.attributedString = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%ld", (long)_likesCount] attributes:attributes]; } - [self addSubnode:_countNode]; // make it tappable easily @@ -51,8 +52,9 @@ + (BOOL) getYesOrNo { int tmp = (arc4random() % 30)+1; - if(tmp % 5 == 0) + if (tmp % 5 == 0) { return YES; + } return NO; } @@ -61,13 +63,9 @@ ASStackLayoutSpec *mainStack = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal spacing:6.0 justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsCenter children:@[_iconNode, _countNode]]; // set sizeRange to make width fixed to 60 - mainStack.sizeRange = ASRelativeSizeRangeMake(ASRelativeSizeMake( - ASRelativeDimensionMakeWithPoints(60.0), - ASRelativeDimensionMakeWithPoints(0.0) - ), ASRelativeSizeMake( - ASRelativeDimensionMakeWithPoints(60.0), - ASRelativeDimensionMakeWithPoints(40.0) - )); + ASRelativeSize min = ASRelativeSizeMake(ASRelativeDimensionMakeWithPoints(60.0), ASRelativeDimensionMakeWithPoints(0.0)); + ASRelativeSize max = ASRelativeSizeMake(ASRelativeDimensionMakeWithPoints(60.0), ASRelativeDimensionMakeWithPoints(40.0)); + mainStack.sizeRange = ASRelativeSizeRangeMake(min, max); return [ASStaticLayoutSpec staticLayoutSpecWithChildren:@[mainStack]]; } diff --git a/examples/SocialAppLayout/Sample/Post.h b/examples/SocialAppLayout/Sample/Post.h index d1e7f7c0aa..58be8bad74 100644 --- a/examples/SocialAppLayout/Sample/Post.h +++ b/examples/SocialAppLayout/Sample/Post.h @@ -13,12 +13,12 @@ @interface Post : NSObject -@property (nonatomic, strong) NSString *username; -@property (nonatomic, strong) NSString *name; -@property (nonatomic, strong) NSString *photo; -@property (nonatomic, strong) NSString *post; -@property (nonatomic, strong) NSString *time; -@property (nonatomic, strong) NSString *media; +@property (nonatomic, copy) NSString *username; +@property (nonatomic, copy) NSString *name; +@property (nonatomic, copy) NSString *photo; +@property (nonatomic, copy) NSString *post; +@property (nonatomic, copy) NSString *time; +@property (nonatomic, copy) NSString *media; @property (nonatomic, assign) NSInteger via; @property (nonatomic, assign) NSInteger likes; diff --git a/examples/SocialAppLayout/Sample/PostNode.h b/examples/SocialAppLayout/Sample/PostNode.h index de3dbb80df..486c9184d8 100644 --- a/examples/SocialAppLayout/Sample/PostNode.h +++ b/examples/SocialAppLayout/Sample/PostNode.h @@ -10,28 +10,10 @@ */ #import -#import "Post.h" -@class LikesNode; -@class CommentsNode; +@class Post; -@interface PostNode : ASCellNode { - - Post *_post; - - ASDisplayNode *_divider; - ASTextNode *_nameNode; - ASTextNode *_usernameNode; - ASTextNode *_timeNode; - ASTextNode *_postNode; - ASImageNode *_viaNode; - ASNetworkImageNode *_avatarNode; - ASNetworkImageNode *_mediaNode; - LikesNode *_likesNode; - CommentsNode *_commentsNode; - ASImageNode *_optionsNode; - -} +@interface PostNode : ASCellNode - (instancetype)initWithPost:(Post *)post; diff --git a/examples/SocialAppLayout/Sample/PostNode.m b/examples/SocialAppLayout/Sample/PostNode.m index bf1c5f22b5..9d29fcd4f3 100644 --- a/examples/SocialAppLayout/Sample/PostNode.m +++ b/examples/SocialAppLayout/Sample/PostNode.m @@ -10,11 +10,26 @@ */ #import "PostNode.h" +#import "Post.h" #import "TextStyles.h" #import "LikesNode.h" #import "CommentsNode.h" -@interface PostNode() +@interface PostNode() + +@property (strong, nonatomic) Post *post; +@property (strong, nonatomic) ASDisplayNode *divider; +@property (strong, nonatomic) ASTextNode *nameNode; +@property (strong, nonatomic) ASTextNode *usernameNode; +@property (strong, nonatomic) ASTextNode *timeNode; +@property (strong, nonatomic) ASTextNode *postNode; +@property (strong, nonatomic) ASImageNode *viaNode; +@property (strong, nonatomic) ASNetworkImageNode *avatarNode; +@property (strong, nonatomic) ASNetworkImageNode *mediaNode; +@property (strong, nonatomic) LikesNode *likesNode; +@property (strong, nonatomic) CommentsNode *commentsNode; +@property (strong, nonatomic) ASImageNode *optionsNode; + @end @implementation PostNode @@ -22,41 +37,35 @@ - (instancetype)initWithPost:(Post *)post { self = [super init]; - - if(self) { - + if (self) { _post = post; - // name node + // Name node _nameNode = [[ASTextNode alloc] init]; - _nameNode.attributedString = [[NSAttributedString alloc] initWithString:_post.name - attributes:[TextStyles nameStyle]]; + _nameNode.attributedString = [[NSAttributedString alloc] initWithString:_post.name attributes:[TextStyles nameStyle]]; _nameNode.maximumNumberOfLines = 1; [self addSubnode:_nameNode]; - // username node + // Username node _usernameNode = [[ASTextNode alloc] init]; - _usernameNode.attributedString = [[NSAttributedString alloc] initWithString:_post.username - attributes:[TextStyles usernameStyle]]; + _usernameNode.attributedString = [[NSAttributedString alloc] initWithString:_post.username attributes:[TextStyles usernameStyle]]; _usernameNode.flexShrink = YES; //if name and username don't fit to cell width, allow username shrink _usernameNode.truncationMode = NSLineBreakByTruncatingTail; _usernameNode.maximumNumberOfLines = 1; - [self addSubnode:_usernameNode]; - // time node + // Time node _timeNode = [[ASTextNode alloc] init]; - _timeNode.attributedString = [[NSAttributedString alloc] initWithString:_post.time - attributes:[TextStyles timeStyle]]; + _timeNode.attributedString = [[NSAttributedString alloc] initWithString:_post.time attributes:[TextStyles timeStyle]]; [self addSubnode:_timeNode]; - // post node + // Post node _postNode = [[ASTextNode alloc] init]; - - // processing URLs in post + + // Processing URLs in post NSString *kLinkAttributeName = @"TextLinkAttributeName"; - if(![_post.post isEqualToString:@""]) { + if (![_post.post isEqualToString:@""]) { NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:_post.post attributes:[TextStyles postStyle]]; @@ -75,7 +84,7 @@ }]; - // configure node to support tappable links + // Configure node to support tappable links _postNode.delegate = self; _postNode.userInteractionEnabled = YES; _postNode.linkAttributeNames = @[ kLinkAttributeName ]; @@ -85,9 +94,9 @@ [self addSubnode:_postNode]; - // media - if(![_post.media isEqualToString:@""]) { + // Media + if (![_post.media isEqualToString:@""]) { _mediaNode = [[ASNetworkImageNode alloc] init]; _mediaNode.backgroundColor = ASDisplayNodeDefaultPlaceholderColor(); @@ -113,7 +122,7 @@ [self addSubnode:_mediaNode]; } - // user pic + // User pic _avatarNode = [[ASNetworkImageNode alloc] init]; _avatarNode.backgroundColor = ASDisplayNodeDefaultPlaceholderColor(); _avatarNode.preferredFrameSize = CGSizeMake(44, 44); @@ -137,19 +146,19 @@ }; [self addSubnode:_avatarNode]; - // hairline cell separator + // Hairline cell separator _divider = [[ASDisplayNode alloc] init]; _divider.backgroundColor = [UIColor lightGrayColor]; [self addSubnode:_divider]; - if(_post.via != 0) { - + // Via + if (_post.via != 0) { _viaNode = [[ASImageNode alloc] init]; _viaNode.image = (_post.via == 1) ? [UIImage imageNamed:@"icon_ios.png"] : [UIImage imageNamed:@"icon_android.png"]; [self addSubnode:_viaNode]; } - // bottom controls + // Bottom controls _likesNode = [[LikesNode alloc] initWithLikesCount:_post.likes]; [self addSubnode:_likesNode]; @@ -159,9 +168,7 @@ _optionsNode = [[ASImageNode alloc] init]; _optionsNode.image = [UIImage imageNamed:@"icon_more"]; [self addSubnode:_optionsNode]; - } - return self; } @@ -175,50 +182,33 @@ - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize { - //Flexible spacer between username and time + // Flexible spacer between username and time ASLayoutSpec *spacer = [[ASLayoutSpec alloc] init]; spacer.flexGrow = YES; - //Horizontal stack for name, username, via icon and time - ASStackLayoutSpec *nameStack; - - //Cases with or without via icon - if(_post.via != 0) { - - nameStack = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal spacing:5.0 justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsCenter children:@[_nameNode, _usernameNode, spacer, _viaNode, _timeNode]]; - - }else { - nameStack = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal spacing:5.0 justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsCenter children:@[_nameNode, _usernameNode, spacer, _timeNode]]; + // Horizontal stack for name, username, via icon and time + NSMutableArray *layoutSpecChildren = [@[_nameNode, _usernameNode, spacer] mutableCopy]; + if (_post.via != 0) { + [layoutSpecChildren addObject:_viaNode]; } + [layoutSpecChildren addObject:_timeNode]; - + ASStackLayoutSpec *nameStack = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal spacing:5.0 justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsCenter children:layoutSpecChildren]; nameStack.alignSelf = ASStackLayoutAlignSelfStretch; // bottom controls horizontal stack ASStackLayoutSpec *controlsStack = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal spacing:10 justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsCenter children:@[_likesNode, _commentsNode, _optionsNode]]; - //add more gaps for control line + // Add more gaps for control line controlsStack.spacingAfter = 3.0; controlsStack.spacingBefore = 3.0; NSMutableArray *mainStackContent = [[NSMutableArray alloc] init]; - [mainStackContent addObject:nameStack]; [mainStackContent addObject:_postNode]; - if(![_post.media isEqualToString:@""]) { - - CGFloat imageRatio; - - if(_mediaNode.image != nil) { - - imageRatio = _mediaNode.image.size.height / _mediaNode.image.size.width; - - }else { - - imageRatio = 0.5; - } - + if (![_post.media isEqualToString:@""]) { + CGFloat imageRatio = (_mediaNode.image != nil ? _mediaNode.image.size.height / _mediaNode.image.size.width : 0.5); ASRatioLayoutSpec *imagePlace = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:imageRatio child:_mediaNode]; imagePlace.spacingAfter = 3.0; imagePlace.spacingBefore = 3.0; @@ -226,14 +216,17 @@ [mainStackContent addObject:imagePlace]; } - [mainStackContent addObject:controlsStack]; - //Vertical spec of cell main content + // Vertical spec of cell main content ASStackLayoutSpec *contentSpec = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical spacing:8.0 justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsStart children:mainStackContent]; + contentSpec.alignItems = ASStackLayoutAlignSelfStretch; + contentSpec.flexShrink = YES; + // Horizontal spec for avatar + ASStackLayoutSpec *avatarContentSpec = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal spacing:8.0 justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsStart children:@[_avatarNode, contentSpec]]; - return [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(10, 64, 10, 10) child:contentSpec]; + return [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(10, 10, 10, 10) child:avatarContentSpec]; } @@ -244,26 +237,23 @@ // Manually layout the divider. CGFloat pixelHeight = 1.0f / [[UIScreen mainScreen] scale]; _divider.frame = CGRectMake(0.0f, 0.0f, self.calculatedSize.width, pixelHeight); - _avatarNode.frame = CGRectMake(10, 10, 44, 44); } -#pragma mark - -#pragma mark ASTextNodeDelegate methods. +#pragma mark - ASTextNodeDelegate methods. - (BOOL)textNode:(ASTextNode *)richTextNode shouldHighlightLinkAttribute:(NSString *)attribute value:(id)value atPoint:(CGPoint)point { - // opt into link highlighting -- tap and hold the link to try it! must enable highlighting on a layer, see -didLoad + // Opt into link highlighting -- tap and hold the link to try it! must enable highlighting on a layer, see -didLoad return YES; } - (void)textNode:(ASTextNode *)richTextNode tappedLinkAttribute:(NSString *)attribute value:(NSURL *)URL atPoint:(CGPoint)point textRange:(NSRange)textRange { - // the node tapped a link, open it + // The node tapped a link, open it [[UIApplication sharedApplication] openURL:URL]; } -#pragma mark - -#pragma mark ASNetworkImageNodeDelegate methods. +#pragma mark - ASNetworkImageNodeDelegate methods. - (void)imageNode:(ASNetworkImageNode *)imageNode didLoadImage:(UIImage *)image { diff --git a/examples/SocialAppLayout/Sample/TextStyles.m b/examples/SocialAppLayout/Sample/TextStyles.m index a561469fe3..153b12407e 100644 --- a/examples/SocialAppLayout/Sample/TextStyles.m +++ b/examples/SocialAppLayout/Sample/TextStyles.m @@ -16,58 +16,58 @@ + (NSDictionary *)nameStyle { return @{ - NSFontAttributeName : [UIFont boldSystemFontOfSize:15.0], - NSForegroundColorAttributeName: [UIColor blackColor] + NSFontAttributeName : [UIFont boldSystemFontOfSize:15.0], + NSForegroundColorAttributeName: [UIColor blackColor] }; } + (NSDictionary *)usernameStyle { return @{ - NSFontAttributeName : [UIFont systemFontOfSize:13.0], - NSForegroundColorAttributeName: [UIColor lightGrayColor] - }; + NSFontAttributeName : [UIFont systemFontOfSize:13.0], + NSForegroundColorAttributeName: [UIColor lightGrayColor] + }; } + (NSDictionary *)timeStyle { return @{ - NSFontAttributeName : [UIFont systemFontOfSize:13.0], - NSForegroundColorAttributeName: [UIColor grayColor] - }; + NSFontAttributeName : [UIFont systemFontOfSize:13.0], + NSForegroundColorAttributeName: [UIColor grayColor] + }; } + (NSDictionary *)postStyle { return @{ - NSFontAttributeName : [UIFont systemFontOfSize:15.0], - NSForegroundColorAttributeName: [UIColor blackColor] - }; + NSFontAttributeName : [UIFont systemFontOfSize:15.0], + NSForegroundColorAttributeName: [UIColor blackColor] + }; } + (NSDictionary *)postLinkStyle { return @{ - NSFontAttributeName : [UIFont systemFontOfSize:15.0], - NSForegroundColorAttributeName: [UIColor colorWithRed:59.0/255.0 green:89.0/255.0 blue:152.0/255.0 alpha:1.0], - NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle) - }; + NSFontAttributeName : [UIFont systemFontOfSize:15.0], + NSForegroundColorAttributeName: [UIColor colorWithRed:59.0/255.0 green:89.0/255.0 blue:152.0/255.0 alpha:1.0], + NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle) + }; } + (NSDictionary *)cellControlStyle { return @{ - NSFontAttributeName : [UIFont systemFontOfSize:13.0], - NSForegroundColorAttributeName: [UIColor lightGrayColor] - }; + NSFontAttributeName : [UIFont systemFontOfSize:13.0], + NSForegroundColorAttributeName: [UIColor lightGrayColor] + }; } + (NSDictionary *)cellControlColoredStyle { return @{ - NSFontAttributeName : [UIFont systemFontOfSize:13.0], - NSForegroundColorAttributeName: [UIColor colorWithRed:59.0/255.0 green:89.0/255.0 blue:152.0/255.0 alpha:1.0] - }; + NSFontAttributeName : [UIFont systemFontOfSize:13.0], + NSForegroundColorAttributeName: [UIColor colorWithRed:59.0/255.0 green:89.0/255.0 blue:152.0/255.0 alpha:1.0] + }; } @end diff --git a/examples/SocialAppLayout/Sample/ViewController.m b/examples/SocialAppLayout/Sample/ViewController.m index ff6abbd3f8..36010f0bd7 100644 --- a/examples/SocialAppLayout/Sample/ViewController.m +++ b/examples/SocialAppLayout/Sample/ViewController.m @@ -15,46 +15,46 @@ #import #import + #include @interface ViewController () -{ - ASTableView *_tableView; - - NSMutableArray *_socialAppDataSource; -} +@property (nonatomic, strong) ASTableView *tableView; +@property (nonatomic, strong) NSMutableArray *socialAppDataSource; @end + @implementation ViewController - (instancetype)init { - if (!(self = [super init])) - return nil; - - _tableView = [[ASTableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain asyncDataFetching:YES]; - _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; // SocialAppNode has its own separator - _tableView.asyncDataSource = self; - _tableView.asyncDelegate = self; - - [self createSocialAppDataSource]; - - self.title = @"Timeline"; - + self = [super init]; + if (self) { + self.title = @"Timeline"; + [self createSocialAppDataSource]; + } return self; } + +- (void)dealloc +{ + _tableView.asyncDataSource = nil; + _tableView.asyncDelegate = nil; +} + - (void)viewDidLoad { [super viewDidLoad]; - [self.view addSubview:_tableView]; -} - -- (void)viewWillLayoutSubviews -{ - _tableView.frame = self.view.bounds; + + self.tableView = [[ASTableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain asyncDataFetching:YES]; + self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; // SocialAppNode has its own separator + self.tableView.asyncDataSource = self; + self.tableView.asyncDelegate = self; + [self.view addSubview:self.tableView]; } - (BOOL)prefersStatusBarHidden @@ -76,7 +76,6 @@ newPost.via = 0; newPost.likes = arc4random_uniform(74); newPost.comments = arc4random_uniform(40); - [_socialAppDataSource addObject:newPost]; newPost = [[Post alloc] init]; @@ -89,7 +88,6 @@ newPost.via = 1; newPost.likes = arc4random_uniform(74); newPost.comments = arc4random_uniform(40); - [_socialAppDataSource addObject:newPost]; newPost = [[Post alloc] init]; @@ -102,7 +100,6 @@ newPost.via = 2; newPost.likes = arc4random_uniform(74); newPost.comments = arc4random_uniform(40); - [_socialAppDataSource addObject:newPost]; newPost = [[Post alloc] init]; @@ -115,29 +112,28 @@ newPost.via = 1; newPost.likes = arc4random_uniform(74); newPost.comments = arc4random_uniform(40); - [_socialAppDataSource addObject:newPost]; } -#pragma mark - -#pragma mark ASTableView. +#pragma mark - ASTableView -- (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath +- (ASCellNodeBlock)tableView:(ASTableView *)tableView nodeBlockForRowAtIndexPath:(nonnull NSIndexPath *)indexPath { - Post *post = _socialAppDataSource[indexPath.row]; - PostNode *node = [[PostNode alloc] initWithPost:post]; - return node; + Post *post = self.socialAppDataSource[indexPath.row]; + return ^{ + return [[PostNode alloc] initWithPost:post]; + }; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return _socialAppDataSource.count; + return self.socialAppDataSource.count; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { PostNode *postNode = (PostNode *)[_tableView nodeForRowAtIndexPath:indexPath]; - Post *post = _socialAppDataSource[indexPath.row]; + Post *post = self.socialAppDataSource[indexPath.row]; BOOL shouldRasterize = postNode.shouldRasterizeDescendants; shouldRasterize = !shouldRasterize;