diff --git a/Source/ASCollectionNode.h b/Source/ASCollectionNode.h index 745a94ce5d..262d52fa12 100644 --- a/Source/ASCollectionNode.h +++ b/Source/ASCollectionNode.h @@ -29,6 +29,8 @@ NS_ASSUME_NONNULL_BEGIN */ @interface ASCollectionNode : ASDisplayNode +- (instancetype)init NS_UNAVAILABLE; + /** * Initializes an ASCollectionNode * diff --git a/Source/ASCollectionNode.mm b/Source/ASCollectionNode.mm index 172055ba7b..9ae9f626bd 100644 --- a/Source/ASCollectionNode.mm +++ b/Source/ASCollectionNode.mm @@ -123,14 +123,6 @@ } } -- (instancetype)init -{ - ASDISPLAYNODE_NOT_DESIGNATED_INITIALIZER(); - UICollectionViewLayout *nilLayout = nil; - self = [self initWithCollectionViewLayout:nilLayout]; // Will throw an exception for lacking a UICV Layout. - return nil; -} - - (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout { return [self initWithFrame:CGRectZero collectionViewLayout:layout layoutFacilitator:nil]; @@ -143,17 +135,14 @@ - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout layoutFacilitator:(id)layoutFacilitator { - __weak __typeof__(self) weakSelf = self; - ASDisplayNodeViewBlock collectionViewBlock = ^UIView *{ - // Variable will be unused if event logging is off. - __unused __typeof__(self) strongSelf = weakSelf; - return [[[strongSelf collectionViewClass] alloc] _initWithFrame:frame collectionViewLayout:layout layoutFacilitator:layoutFacilitator eventLog:ASDisplayNodeGetEventLog(strongSelf)]; - }; - - if (self = [super initWithViewBlock:collectionViewBlock didLoadBlock:nil]) { - return self; + if (self = [super init]) { + __weak __typeof__(self) weakSelf = self; + [self setViewBlock:^{ + __typeof__(self) strongSelf = weakSelf; + return [[[strongSelf collectionViewClass] alloc] _initWithFrame:frame collectionViewLayout:layout layoutFacilitator:layoutFacilitator eventLog:ASDisplayNodeGetEventLog(strongSelf)]; + }]; } - return nil; + return self; } #pragma mark ASDisplayNode diff --git a/Source/ASDisplayNode.h b/Source/ASDisplayNode.h index deeb1e1ca9..797073debf 100644 --- a/Source/ASDisplayNode.h +++ b/Source/ASDisplayNode.h @@ -125,7 +125,7 @@ extern NSInteger const ASDefaultDrawingPriority; * @return An ASDisplayNode instance whose view will be a subclass that enables asynchronous rendering, and passes * through -layout and touch handling methods. */ -- (instancetype)init; +- (instancetype)init NS_DESIGNATED_INITIALIZER; /** @@ -183,6 +183,28 @@ extern NSInteger const ASDefaultDrawingPriority; */ - (void)onDidLoad:(ASDisplayNodeDidLoadBlock)body; +/** + * Set the block that should be used to load this node's view. + * + * @param viewBlock The block that creates a view for this node. + * + * @precondition The node is not yet loaded. + * + * @note You will usually NOT call this. See the limitations documented in @c initWithViewBlock: + */ +- (void)setViewBlock:(ASDisplayNodeViewBlock)viewBlock; + +/** + * Set the block that should be used to load this node's layer. + * + * @param viewBlock The block that creates a layer for this node. + * + * @precondition The node is not yet loaded. + * + * @note You will usually NOT call this. See the limitations documented in @c initWithLayerBlock: + */ +- (void)setLayerBlock:(ASDisplayNodeLayerBlock)layerBlock; + /** * @abstract Returns whether the node is synchronous. * diff --git a/Source/ASDisplayNode.mm b/Source/ASDisplayNode.mm index 2e5278c184..b4089791e5 100644 --- a/Source/ASDisplayNode.mm +++ b/Source/ASDisplayNode.mm @@ -316,12 +316,11 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) - (instancetype)initWithViewClass:(Class)viewClass { - if (!(self = [super init])) + if (!(self = [self init])) return nil; ASDisplayNodeAssert([viewClass isSubclassOfClass:[UIView class]], @"should initialize with a subclass of UIView"); - [self _initializeInstance]; _viewClass = viewClass; _flags.synchronous = ![viewClass isSubclassOfClass:[_ASDisplayView class]]; @@ -330,13 +329,12 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) - (instancetype)initWithLayerClass:(Class)layerClass { - if (!(self = [super init])) { + if (!(self = [self init])) { return nil; } ASDisplayNodeAssert([layerClass isSubclassOfClass:[CALayer class]], @"should initialize with a subclass of CALayer"); - [self _initializeInstance]; _layerClass = layerClass; _flags.synchronous = ![layerClass isSubclassOfClass:[_ASDisplayLayer class]]; _flags.layerBacked = YES; @@ -346,26 +344,18 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) - (instancetype)initWithViewBlock:(ASDisplayNodeViewBlock)viewBlock { - return [self _initWithViewBlock:viewBlock didLoadBlock:nil]; -} -- (instancetype)initWithViewBlock:(ASDisplayNodeViewBlock)viewBlock didLoadBlock:(ASDisplayNodeDidLoadBlock)didLoadBlock -{ - return [self _initWithViewBlock:viewBlock didLoadBlock:didLoadBlock]; + return [self initWithViewBlock:viewBlock didLoadBlock:nil]; } -- (instancetype)_initWithViewBlock:(ASDisplayNodeViewBlock)viewBlock didLoadBlock:(ASDisplayNodeDidLoadBlock)didLoadBlock +- (instancetype)initWithViewBlock:(ASDisplayNodeViewBlock)viewBlock didLoadBlock:(ASDisplayNodeDidLoadBlock)didLoadBlock { - if (!(self = [super init])) { + if (!(self = [self init])) { return nil; } - - ASDisplayNodeAssertNotNil(viewBlock, @"should initialize with a valid block that returns a UIView"); - - [self _initializeInstance]; - _viewBlock = viewBlock; - _flags.synchronous = YES; + + [self setViewBlock:viewBlock]; if (didLoadBlock != nil) { - _onDidLoadBlocks = [NSMutableArray arrayWithObject:didLoadBlock]; + [self onDidLoad:didLoadBlock]; } return self; @@ -373,33 +363,42 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) - (instancetype)initWithLayerBlock:(ASDisplayNodeLayerBlock)layerBlock { - return [self _initWithLayerBlock:layerBlock didLoadBlock:nil]; + return [self initWithLayerBlock:layerBlock didLoadBlock:nil]; } - (instancetype)initWithLayerBlock:(ASDisplayNodeLayerBlock)layerBlock didLoadBlock:(ASDisplayNodeDidLoadBlock)didLoadBlock { - return [self _initWithLayerBlock:layerBlock didLoadBlock:didLoadBlock]; -} - -- (instancetype)_initWithLayerBlock:(ASDisplayNodeLayerBlock)layerBlock didLoadBlock:(ASDisplayNodeDidLoadBlock)didLoadBlock -{ - if (!(self = [super init])) { + if (!(self = [self init])) { return nil; } - ASDisplayNodeAssertNotNil(layerBlock, @"should initialize with a valid block that returns a CALayer"); - - [self _initializeInstance]; - _layerBlock = layerBlock; - _flags.synchronous = YES; - _flags.layerBacked = YES; + [self setLayerBlock:layerBlock]; if (didLoadBlock != nil) { - _onDidLoadBlocks = [NSMutableArray arrayWithObject:didLoadBlock]; + [self onDidLoad:didLoadBlock]; } return self; } +- (void)setViewBlock:(ASDisplayNodeViewBlock)viewBlock +{ + ASDisplayNodeAssertFalse(self.nodeLoaded); + ASDisplayNodeAssertNotNil(viewBlock, @"should initialize with a valid block that returns a UIView"); + + _viewBlock = viewBlock; + _flags.synchronous = YES; +} + +- (void)setLayerBlock:(ASDisplayNodeLayerBlock)layerBlock +{ + ASDisplayNodeAssertFalse(self.nodeLoaded); + ASDisplayNodeAssertNotNil(layerBlock, @"should initialize with a valid block that returns a CALayer"); + + _layerBlock = layerBlock; + _flags.synchronous = YES; + _flags.layerBacked = YES; +} + - (void)onDidLoad:(ASDisplayNodeDidLoadBlock)body { ASDN::MutexLocker l(__instanceLock__); diff --git a/Source/ASScrollNode.mm b/Source/ASScrollNode.mm index 6e9afc69c7..7d257dd99b 100644 --- a/Source/ASScrollNode.mm +++ b/Source/ASScrollNode.mm @@ -64,7 +64,10 @@ - (instancetype)init { - return [super initWithViewBlock:^UIView *{ return [[ASScrollView alloc] init]; }]; + if (self = [super init]) { + [self setViewBlock:^UIView *{ return [[ASScrollView alloc] init]; }]; + } + return self; } - (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize diff --git a/Source/ASTableNode.h b/Source/ASTableNode.h index 4b69f9782e..61d5909112 100644 --- a/Source/ASTableNode.h +++ b/Source/ASTableNode.h @@ -29,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN @interface ASTableNode : ASDisplayNode - (instancetype)init; // UITableViewStylePlain -- (instancetype)initWithStyle:(UITableViewStyle)style; +- (instancetype)initWithStyle:(UITableViewStyle)style NS_DESIGNATED_INITIALIZER; @property (strong, nonatomic, readonly) ASTableView *view; diff --git a/Source/ASTableNode.mm b/Source/ASTableNode.mm index b771744fec..7f27bef456 100644 --- a/Source/ASTableNode.mm +++ b/Source/ASTableNode.mm @@ -72,40 +72,22 @@ #pragma mark Lifecycle -- (instancetype)_initWithTableView:(ASTableView *)tableView -{ - // Avoid a retain cycle. In this case, the ASTableView is creating us, and strongly retains us. - ASTableView * __weak weakTableView = tableView; - if (self = [super initWithViewBlock:^UIView *{ return weakTableView; }]) { - __unused __weak ASTableView *view = [self view]; - return self; - } - return nil; -} - -- (instancetype)_initWithFrame:(CGRect)frame style:(UITableViewStyle)style dataControllerClass:(Class)dataControllerClass -{ - __weak __typeof__(self) weakSelf = self; - ASDisplayNodeViewBlock tableViewBlock = ^UIView *{ - // Variable will be unused if event logging is off. - __unused __typeof__(self) strongSelf = weakSelf; - return [[ASTableView alloc] _initWithFrame:frame style:style dataControllerClass:dataControllerClass eventLog:ASDisplayNodeGetEventLog(strongSelf)]; - }; - - if (self = [super initWithViewBlock:tableViewBlock]) { - return self; - } - return nil; -} - - (instancetype)initWithStyle:(UITableViewStyle)style { - return [self _initWithFrame:CGRectZero style:style dataControllerClass:nil]; + if (self = [super init]) { + __weak __typeof__(self) weakSelf = self; + [self setViewBlock:^{ + // Variable will be unused if event logging is off. + __unused __typeof__(self) strongSelf = weakSelf; + return [[ASTableView alloc] _initWithFrame:CGRectZero style:style dataControllerClass:nil eventLog:ASDisplayNodeGetEventLog(strongSelf)]; + }]; + } + return self; } - (instancetype)init { - return [self _initWithFrame:CGRectZero style:UITableViewStylePlain dataControllerClass:nil]; + return [self initWithStyle:UITableViewStylePlain]; } #pragma mark ASDisplayNode diff --git a/Source/ASTableView.mm b/Source/ASTableView.mm index d1c4558596..7a8353fe0c 100644 --- a/Source/ASTableView.mm +++ b/Source/ASTableView.mm @@ -121,10 +121,6 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; #pragma mark - #pragma mark ASTableView -@interface ASTableNode () -- (instancetype)_initWithTableView:(ASTableView *)tableView; -@end - @interface ASTableView () { ASTableViewProxy *_proxyDataSource; diff --git a/Source/Private/ASDisplayNodeInternal.h b/Source/Private/ASDisplayNodeInternal.h index f2b6a1932f..66e6f3b11a 100644 --- a/Source/Private/ASDisplayNodeInternal.h +++ b/Source/Private/ASDisplayNodeInternal.h @@ -240,10 +240,10 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo - (void)displayImmediately; /// Alternative initialiser for backing with a custom view class. Supports asynchronous display with _ASDisplayView subclasses. -- (nullable instancetype)initWithViewClass:(Class)viewClass; +- (instancetype)initWithViewClass:(Class)viewClass; /// Alternative initialiser for backing with a custom layer class. Supports asynchronous display with _ASDisplayLayer subclasses. -- (nullable instancetype)initWithLayerClass:(Class)layerClass; +- (instancetype)initWithLayerClass:(Class)layerClass; @property (nonatomic, assign) CGFloat contentsScaleForDisplay; diff --git a/examples/Swift/Sample/TailLoadingCellNode.swift b/examples/Swift/Sample/TailLoadingCellNode.swift index 4e995443dc..b3a0bff6f2 100644 --- a/examples/Swift/Sample/TailLoadingCellNode.swift +++ b/examples/Swift/Sample/TailLoadingCellNode.swift @@ -55,7 +55,10 @@ final class SpinnerNode: ASDisplayNode { } override init() { - super.init(viewBlock: { UIActivityIndicatorView(activityIndicatorStyle: .Gray) }, didLoadBlock: nil) + super.init() + setViewBlock { + UIActivityIndicatorView(activityIndicatorStyle: .Gray) + } // Set spinner node to default size of the activitiy indicator view self.style.preferredSize = CGSizeMake(20.0, 20.0)