From 814f72535c28171382988a278e97d4905eaffd75 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Wed, 16 Sep 2015 15:15:07 -0700 Subject: [PATCH 01/60] Add nullability annotations for public API --- AsyncDisplayKit/ASCellNode.h | 3 ++ AsyncDisplayKit/ASCollectionNode.h | 4 ++ AsyncDisplayKit/ASCollectionNode.m | 2 +- AsyncDisplayKit/ASCollectionView.h | 19 ++++--- AsyncDisplayKit/ASControlNode+Subclasses.h | 13 +++-- AsyncDisplayKit/ASControlNode.h | 11 +++-- AsyncDisplayKit/ASDisplayNode+Subclasses.h | 22 +++++---- AsyncDisplayKit/ASDisplayNode.h | 49 ++++++++++--------- AsyncDisplayKit/ASDisplayNodeExtras.h | 22 +++++---- AsyncDisplayKit/ASDisplayNodeExtras.mm | 10 ++-- AsyncDisplayKit/ASEditableTextNode.h | 5 +- AsyncDisplayKit/ASImageNode.h | 8 +-- AsyncDisplayKit/ASImageNode.mm | 2 +- AsyncDisplayKit/ASMultiplexImageNode.h | 33 +++++++------ AsyncDisplayKit/ASNetworkImageNode.h | 11 +++-- AsyncDisplayKit/ASScrollNode.h | 3 ++ AsyncDisplayKit/ASTableView.h | 17 ++++--- AsyncDisplayKit/ASTableViewProtocols.h | 26 +++++----- AsyncDisplayKit/ASTextNode.h | 18 ++++--- .../Swift/Sample.xcodeproj/project.pbxproj | 2 + examples/Swift/Sample/ViewController.swift | 2 +- 21 files changed, 170 insertions(+), 112 deletions(-) diff --git a/AsyncDisplayKit/ASCellNode.h b/AsyncDisplayKit/ASCellNode.h index 12cc6302..380eddbe 100644 --- a/AsyncDisplayKit/ASCellNode.h +++ b/AsyncDisplayKit/ASCellNode.h @@ -8,6 +8,7 @@ #import +NS_ASSUME_NONNULL_BEGIN /** * Generic cell node. Subclass ASCellNode instead of to use . @@ -43,3 +44,5 @@ @property (nonatomic, copy) NSString *text; @end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/AsyncDisplayKit/ASCollectionNode.h b/AsyncDisplayKit/ASCollectionNode.h index c0489b22..46301402 100644 --- a/AsyncDisplayKit/ASCollectionNode.h +++ b/AsyncDisplayKit/ASCollectionNode.h @@ -8,6 +8,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** * ASCollectionNode is a node based class that wraps an ASCollectionView. It can be used * as a subnode of another node, and provide room for many (great) features and improvements later on. @@ -19,3 +21,5 @@ @property (nonatomic, readonly) ASCollectionView *view; @end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/AsyncDisplayKit/ASCollectionNode.m b/AsyncDisplayKit/ASCollectionNode.m index 2a131bfe..29332897 100644 --- a/AsyncDisplayKit/ASCollectionNode.m +++ b/AsyncDisplayKit/ASCollectionNode.m @@ -13,7 +13,7 @@ - (instancetype)init { ASDISPLAYNODE_NOT_DESIGNATED_INITIALIZER(); - self = [self initWithCollectionViewLayout:nil]; // Will throw an exception for lacking a UICV Layout. + self = [self initWithCollectionViewLayout:[UICollectionViewFlowLayout new]]; return nil; } diff --git a/AsyncDisplayKit/ASCollectionView.h b/AsyncDisplayKit/ASCollectionView.h index 47568355..70264fc4 100644 --- a/AsyncDisplayKit/ASCollectionView.h +++ b/AsyncDisplayKit/ASCollectionView.h @@ -18,6 +18,7 @@ @protocol ASCollectionViewDataSource; @protocol ASCollectionViewDelegate; +NS_ASSUME_NONNULL_BEGIN /** * Node-based collection view. @@ -90,7 +91,7 @@ * Boolean parameter that contains the value YES if all of the related animations completed successfully or * NO if they were interrupted. This parameter may be nil. If supplied, the block is run on the main thread. */ -- (void)performBatchAnimated:(BOOL)animated updates:(void (^)())updates completion:(void (^)(BOOL))completion; +- (void)performBatchAnimated:(BOOL)animated updates:(void (^ _Nullable)())updates completion:(void (^ _Nullable)(BOOL))completion; /** * Perform a batch of updates asynchronously. This method must be called from the main thread. @@ -101,7 +102,7 @@ * Boolean parameter that contains the value YES if all of the related animations completed successfully or * NO if they were interrupted. This parameter may be nil. If supplied, the block is run on the main thread. */ -- (void)performBatchUpdates:(void (^)())updates completion:(void (^)(BOOL))completion; +- (void)performBatchUpdates:(void (^ _Nullable)())updates completion:(void (^ _Nullable)(BOOL))completion; /** * Reload everything from scratch, destroying the working range and all cached nodes. @@ -110,7 +111,7 @@ * the main thread. * @warning This method is substantially more expensive than UICollectionView's version. */ -- (void)reloadDataWithCompletion:(void (^)())completion; +- (void)reloadDataWithCompletion:(void (^ _Nullable)())completion; /** * Reload everything from scratch, destroying the working range and all cached nodes. @@ -169,7 +170,7 @@ * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)insertItemsAtIndexPaths:(NSArray *)indexPaths; +- (void)insertItemsAtIndexPaths:(NSArray *)indexPaths; /** * Deletes the items specified by an array of index paths. @@ -179,7 +180,7 @@ * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)deleteItemsAtIndexPaths:(NSArray *)indexPaths; +- (void)deleteItemsAtIndexPaths:(NSArray *)indexPaths; /** * Reloads the specified items. @@ -189,7 +190,7 @@ * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)reloadItemsAtIndexPaths:(NSArray *)indexPaths; +- (void)reloadItemsAtIndexPaths:(NSArray *)indexPaths; /** * Moves the item at a specified location to a destination location. @@ -217,7 +218,7 @@ * * @returns an array containing the nodes being displayed on screen. */ -- (NSArray *)visibleNodes; +- (NSArray *)visibleNodes; /** * Query the sized node at `indexPath` for its calculatedSize. @@ -303,7 +304,7 @@ @optional - (void)collectionView:(ASCollectionView *)collectionView willDisplayNodeForItemAtIndexPath:(NSIndexPath *)indexPath; -- (void)collectionView:(ASCollectionView *)collectionView didEndDisplayingNodeForItemAtIndexPath:(NSIndexPath*)indexPath; +- (void)collectionView:(ASCollectionView *)collectionView didEndDisplayingNodeForItemAtIndexPath:(NSIndexPath *)indexPath; /** * Receive a message that the collectionView is near the end of its data set and more data should be fetched if @@ -353,3 +354,5 @@ @property (nonatomic, assign) ASRangeTuningParameters rangeTuningParameters ASDISPLAYNODE_DEPRECATED; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASControlNode+Subclasses.h b/AsyncDisplayKit/ASControlNode+Subclasses.h index 062f2154..90c5f68e 100644 --- a/AsyncDisplayKit/ASControlNode+Subclasses.h +++ b/AsyncDisplayKit/ASControlNode+Subclasses.h @@ -8,6 +8,7 @@ #import +NS_ASSUME_NONNULL_BEGIN /** * The subclass header _ASControlNode+Subclasses_ defines methods to be @@ -24,7 +25,7 @@ @param touchEvent An event object encapsulating the information specific to the user event. @discussion ASControlNode implements this method to send all action messages associated with controlEvents. The list of targets is constructed from prior invocations of addTarget:action:forControlEvents:. */ -- (void)sendActionsForControlEvents:(ASControlNodeEvent)controlEvents withEvent:(UIEvent *)touchEvent; +- (void)sendActionsForControlEvents:(ASControlNodeEvent)controlEvents withEvent:(nullable UIEvent *)touchEvent; /** @abstract Sent to the control when tracking begins. @@ -32,7 +33,7 @@ @param touchEvent An event object encapsulating the information specific to the user event. @result YES if the receiver should respond continuously (respond when touch is dragged); NO otherwise. */ -- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)touchEvent; +- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(nullable UIEvent *)touchEvent; /** @abstract Sent continuously to the control as it tracks a touch within the control's bounds. @@ -40,20 +41,20 @@ @param touchEvent An event object encapsulating the information specific to the user event. @result YES if touch tracking should continue; NO otherwise. */ -- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)touchEvent; +- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(nullable UIEvent *)touchEvent; /** @abstract Sent to the control when tracking should be cancelled. @param touchEvent An event object encapsulating the information specific to the user event. This parameter may be nil, indicating that the cancelation was caused by something other than an event, such as the display node being removed from its supernode. */ -- (void)cancelTrackingWithEvent:(UIEvent *)touchEvent; +- (void)cancelTrackingWithEvent:(nullable UIEvent *)touchEvent; /** @abstract Sent to the control when the last touch completely ends, telling it to stop tracking. @param touch The touch that ended. @param touchEvent An event object encapsulating the information specific to the user event. */ -- (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)touchEvent; +- (void)endTrackingWithTouch:(nullable UITouch *)touch withEvent:(nullable UIEvent *)touchEvent; /** @abstract Settable version of highlighted property. @@ -61,3 +62,5 @@ @property (nonatomic, readwrite, assign, getter=isHighlighted) BOOL highlighted; @end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/AsyncDisplayKit/ASControlNode.h b/AsyncDisplayKit/ASControlNode.h index d08a09c6..28a40ad5 100644 --- a/AsyncDisplayKit/ASControlNode.h +++ b/AsyncDisplayKit/ASControlNode.h @@ -8,6 +8,7 @@ #import +NS_ASSUME_NONNULL_BEGIN /** @abstract Kinds of events possible for control nodes. @@ -75,7 +76,7 @@ typedef NS_OPTIONS(NSUInteger, ASControlNodeEvent) @param controlEvents A bitmask specifying the control events for which the action message is sent. May not be 0. See "Control Events" for bitmask constants. @discussion You may call this method multiple times, and you may specify multiple target-action pairs for a particular event. Targets are held weakly. */ -- (void)addTarget:(id)target action:(SEL)action forControlEvents:(ASControlNodeEvent)controlEvents; +- (void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(ASControlNodeEvent)controlEvents; /** @abstract Returns the actions that are associated with a target and a particular control event. @@ -83,7 +84,7 @@ typedef NS_OPTIONS(NSUInteger, ASControlNodeEvent) @param controlEvent A single constant of type ASControlNodeEvent that specifies a particular user action on the control; for a list of these constants, see "Control Events". May not be 0 or ASControlNodeEventAllEvents. @result An array of selector names as NSString objects, or nil if there are no action selectors associated with controlEvent. */ -- (NSArray *)actionsForTarget:(id)target forControlEvent:(ASControlNodeEvent)controlEvent; +- (nullable NSArray *)actionsForTarget:(id)target forControlEvent:(ASControlNodeEvent)controlEvent; /** @abstract Returns all target objects associated with the receiver. @@ -97,13 +98,15 @@ typedef NS_OPTIONS(NSUInteger, ASControlNodeEvent) @param action A selector identifying an action message. Pass NULL to remove all action messages paired with target. @param controlEvents A bitmask specifying the control events associated with target and action. See "Control Events" for bitmask constants. May not be 0. */ -- (void)removeTarget:(id)target action:(SEL)action forControlEvents:(ASControlNodeEvent)controlEvents; +- (void)removeTarget:(nullable id)target action:(nullable SEL)action forControlEvents:(ASControlNodeEvent)controlEvents; /** @abstract Sends the actions for the control events for a particular event. @param controlEvents A bitmask specifying the control events for which to send actions. See "Control Events" for bitmask constants. May not be 0. @param event The event which triggered these control actions. May be nil. */ -- (void)sendActionsForControlEvents:(ASControlNodeEvent)controlEvents withEvent:(UIEvent *)event; +- (void)sendActionsForControlEvents:(ASControlNodeEvent)controlEvents withEvent:(nullable UIEvent *)event; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASDisplayNode+Subclasses.h b/AsyncDisplayKit/ASDisplayNode+Subclasses.h index 44b81ac1..5814376d 100644 --- a/AsyncDisplayKit/ASDisplayNode+Subclasses.h +++ b/AsyncDisplayKit/ASDisplayNode+Subclasses.h @@ -15,6 +15,8 @@ @class ASLayoutSpec; +NS_ASSUME_NONNULL_BEGIN + /** * The subclass header _ASDisplayNode+Subclasses_ defines the following methods that either must or can be overriden by * subclasses of ASDisplayNode. @@ -85,7 +87,7 @@ * * @warning Subclasses must not override this; it returns the last cached layout and is never expensive. */ -@property (nonatomic, readonly, assign) ASLayout *calculatedLayout; +@property (nullable, nonatomic, readonly, assign) ASLayout *calculatedLayout; /** @name View Lifecycle */ @@ -208,7 +210,7 @@ * * @note Called on the display queue and/or main queue (MUST BE THREAD SAFE) */ -+ (UIImage *)displayWithParameters:(id)parameters ++ (nullable UIImage *)displayWithParameters:(id)parameters isCancelled:(asdisplaynode_iscancelled_block_t)isCancelledBlock; /** @@ -305,7 +307,7 @@ * @param touches A set of UITouch instances. * @param event A UIEvent associated with the touch. */ -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; +- (void)touchesBegan:(NSSet *)touches withEvent:(nullable UIEvent *)event; /** * @abstract Tells the node when touches moved in its view. @@ -313,7 +315,7 @@ * @param touches A set of UITouch instances. * @param event A UIEvent associated with the touch. */ -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; +- (void)touchesMoved:(NSSet *)touches withEvent:(nullable UIEvent *)event; /** * @abstract Tells the node when touches ended in its view. @@ -321,7 +323,7 @@ * @param touches A set of UITouch instances. * @param event A UIEvent associated with the touch. */ -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; +- (void)touchesEnded:(NSSet *)touches withEvent:(nullable UIEvent *)event; /** * @abstract Tells the node when touches was cancelled in its view. @@ -329,7 +331,7 @@ * @param touches A set of UITouch instances. * @param event A UIEvent associated with the touch. */ -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event; +- (void)touchesCancelled:(NSSet *)touches withEvent:(nullable UIEvent *)event; /** @name Managing Gesture Recognizers */ @@ -359,7 +361,7 @@ * 1) allows sending events to plain UIViews that don't have attached nodes, * 2) hitTest: is never called before the views are created. */ -- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event; +- (UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event; /** @name Observing node-related changes */ @@ -410,7 +412,7 @@ * * @note Called on the display queue and/or main queue (MUST BE THREAD SAFE) */ -- (UIImage *)placeholderImage; +- (nullable UIImage *)placeholderImage; /** @name Description */ @@ -428,8 +430,10 @@ @interface ASDisplayNode (ASDisplayNodePrivate) // This method has proven helpful in a few rare scenarios, similar to a category extension on UIView, // but it's considered private API for now and its use should not be encouraged. -- (ASDisplayNode *)_supernodeWithClass:(Class)supernodeClass; +- (nullable ASDisplayNode *)_supernodeWithClass:(Class)supernodeClass; @end #define ASDisplayNodeAssertThreadAffinity(viewNode) ASDisplayNodeAssert(!viewNode || ASDisplayNodeThreadIsMain() || !(viewNode).nodeLoaded, @"Incorrect display node thread affinity") #define ASDisplayNodeCAssertThreadAffinity(viewNode) ASDisplayNodeCAssert(!viewNode || ASDisplayNodeThreadIsMain() || !(viewNode).nodeLoaded, @"Incorrect display node thread affinity") + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index 11a138ea..0cfdae93 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -15,17 +15,19 @@ #import +NS_ASSUME_NONNULL_BEGIN + @class ASDisplayNode; /** * UIView creation block. Used to create the backing view of a new display node. */ -typedef UIView *(^ASDisplayNodeViewBlock)(); +typedef UIView * _Nonnull(^ASDisplayNodeViewBlock)(); /** * CALayer creation block. Used to create the backing layer of a new display node. */ -typedef CALayer *(^ASDisplayNodeLayerBlock)(); +typedef CALayer * _Nonnull(^ASDisplayNodeLayerBlock)(); /** * ASDisplayNode loaded callback block. This block is called BEFORE the -didLoad method and is always called on the main thread. @@ -60,7 +62,7 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); * @return An ASDisplayNode instance whose view will be a subclass that enables asynchronous rendering, and passes * through -layout and touch handling methods. */ -- (id)init; +- (instancetype)init; /** @@ -71,7 +73,7 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); * @return An ASDisplayNode instance that loads its view with the given block that is guaranteed to run on the main * queue. The view will render synchronously and -layout and touch handling methods on the node will not be called. */ -- (id)initWithViewBlock:(ASDisplayNodeViewBlock)viewBlock; +- (instancetype)initWithViewBlock:(ASDisplayNodeViewBlock)viewBlock; /** * @abstract Alternative initializer with a block to create the backing view. @@ -82,7 +84,7 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); * @return An ASDisplayNode instance that loads its view with the given block that is guaranteed to run on the main * queue. The view will render synchronously and -layout and touch handling methods on the node will not be called. */ -- (id)initWithViewBlock:(ASDisplayNodeViewBlock)viewBlock didLoadBlock:(ASDisplayNodeDidLoadBlock)didLoadBlock; +- (instancetype)initWithViewBlock:(ASDisplayNodeViewBlock)viewBlock didLoadBlock:(nullable ASDisplayNodeDidLoadBlock)didLoadBlock; /** * @abstract Alternative initializer with a block to create the backing layer. @@ -92,7 +94,7 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); * @return An ASDisplayNode instance that loads its layer with the given block that is guaranteed to run on the main * queue. The layer will render synchronously and -layout and touch handling methods on the node will not be called. */ -- (id)initWithLayerBlock:(ASDisplayNodeLayerBlock)layerBlock; +- (instancetype)initWithLayerBlock:(ASDisplayNodeLayerBlock)layerBlock; /** * @abstract Alternative initializer with a block to create the backing layer. @@ -103,7 +105,7 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); * @return An ASDisplayNode instance that loads its layer with the given block that is guaranteed to run on the main * queue. The layer will render synchronously and -layout and touch handling methods on the node will not be called. */ -- (id)initWithLayerBlock:(ASDisplayNodeLayerBlock)layerBlock didLoadBlock:(ASDisplayNodeDidLoadBlock)didLoadBlock; +- (instancetype)initWithLayerBlock:(ASDisplayNodeLayerBlock)layerBlock didLoadBlock:(nullable ASDisplayNodeDidLoadBlock)didLoadBlock; /** @name Properties */ @@ -295,7 +297,7 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); /** * @abstract The receiver's immediate subnodes. */ -@property (nonatomic, readonly, retain) NSArray *subnodes; +@property (nonatomic, readonly, retain) NSArray *subnodes; /** * @abstract The receiver's supernode. @@ -454,7 +456,7 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); * * @return YES if point is inside the receiver's bounds; otherwise, NO. */ -- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event; +- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event; /** @name Converting Between View Coordinate Systems */ @@ -468,7 +470,7 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); * * @return The point converted to the coordinate system of node. */ -- (CGPoint)convertPoint:(CGPoint)point toNode:(ASDisplayNode *)node; +- (CGPoint)convertPoint:(CGPoint)point toNode:(nullable ASDisplayNode *)node; /** @@ -479,7 +481,7 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); * * @return The point converted to the local coordinate system (bounds) of the receiver. */ -- (CGPoint)convertPoint:(CGPoint)point fromNode:(ASDisplayNode *)node; +- (CGPoint)convertPoint:(CGPoint)point fromNode:(nullable ASDisplayNode *)node; /** @@ -490,7 +492,7 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); * * @return The converted rectangle. */ -- (CGRect)convertRect:(CGRect)rect toNode:(ASDisplayNode *)node; +- (CGRect)convertRect:(CGRect)rect toNode:(nullable ASDisplayNode *)node; /** * @abstract Converts a rectangle from the coordinate system of another node to that of the receiver. @@ -500,7 +502,7 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); * * @return The converted rectangle. */ -- (CGRect)convertRect:(CGRect)rect fromNode:(ASDisplayNode *)node; +- (CGRect)convertRect:(CGRect)rect fromNode:(nullable ASDisplayNode *)node; /** @name UIResponder methods */ @@ -510,7 +512,7 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); - (BOOL)canResignFirstResponder; // default==YES - (BOOL)resignFirstResponder; // default==NO (no-op) - (BOOL)isFirstResponder; -- (BOOL)canPerformAction:(SEL)action withSender:(id)sender; +- (BOOL)canPerformAction:(SEL)action withSender:(nullable id)sender; @end @@ -583,7 +585,7 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); @property (atomic, assign) CGFloat contentsScale; // default=1.0f. See @contentsScaleForDisplay for more info @property (atomic, assign) CATransform3D transform; // default=CATransform3DIdentity @property (atomic, assign) CATransform3D subnodeTransform; // default=CATransform3DIdentity -@property (atomic, copy) NSString *name; // default=nil. Use this to tag your layers in the server-recurse-description / pca or for your own purposes +@property (atomic, copy, nullable) NSString *name; // default=nil. Use this to tag your layers in the server-recurse-description / pca or for your own purposes /** * @abstract The node view's background color. @@ -591,9 +593,9 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); * @discussion In contrast to UIView, setting a transparent color will not set opaque = NO. * This only affects nodes that implement +drawRect like ASTextNode. */ -@property (atomic, retain) UIColor *backgroundColor; // default=nil +@property (atomic, retain, nullable) UIColor *backgroundColor; // default=nil -@property (atomic, retain) UIColor *tintColor; // default=Blue +@property (atomic, retain, null_resettable) UIColor *tintColor; // default=Blue - (void)tintColorDidChange; // Notifies the node when the tintColor has changed. /** @@ -617,18 +619,18 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); // Accessibility support @property (atomic, assign) BOOL isAccessibilityElement; -@property (atomic, copy) NSString *accessibilityLabel; -@property (atomic, copy) NSString *accessibilityHint; -@property (atomic, copy) NSString *accessibilityValue; +@property (nullable, atomic, copy) NSString *accessibilityLabel; +@property (nullable, atomic, copy) NSString *accessibilityHint; +@property (nullable, atomic, copy) NSString *accessibilityValue; @property (atomic, assign) UIAccessibilityTraits accessibilityTraits; @property (atomic, assign) CGRect accessibilityFrame; -@property (atomic, retain) NSString *accessibilityLanguage; +@property (nullable, atomic, retain) NSString *accessibilityLanguage; @property (atomic, assign) BOOL accessibilityElementsHidden; @property (atomic, assign) BOOL accessibilityViewIsModal; @property (atomic, assign) BOOL shouldGroupAccessibilityChildren; // Accessibility identification support -@property (nonatomic, copy) NSString *accessibilityIdentifier; +@property (nullable, nonatomic, copy) NSString *accessibilityIdentifier; @end @@ -659,6 +661,7 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); - (void)addSubnode:(ASDisplayNode *)node; @end + @interface ASDisplayNode (Deprecated) - (void)reclaimMemory ASDISPLAYNODE_DEPRECATED; @@ -666,3 +669,5 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); @property (nonatomic, assign) BOOL placeholderFadesOut ASDISPLAYNODE_DEPRECATED; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASDisplayNodeExtras.h b/AsyncDisplayKit/ASDisplayNodeExtras.h index 5ce6ac2b..521dce25 100644 --- a/AsyncDisplayKit/ASDisplayNodeExtras.h +++ b/AsyncDisplayKit/ASDisplayNodeExtras.h @@ -12,22 +12,24 @@ #import #import +NS_ASSUME_NONNULL_BEGIN + ASDISPLAYNODE_EXTERN_C_BEGIN /** Given a layer, returns the associated display node, if any. */ -extern ASDisplayNode *ASLayerToDisplayNode(CALayer *layer); +extern ASDisplayNode * _Nullable ASLayerToDisplayNode(CALayer * _Nullable layer); /** Given a view, returns the associated display node, if any. */ -extern ASDisplayNode *ASViewToDisplayNode(UIView *view); +extern ASDisplayNode * _Nullable ASViewToDisplayNode(UIView * _Nullable view); /** Given a display node, traverses up the layer tree hierarchy, returning the first display node that passes block. */ -extern id ASDisplayNodeFind(ASDisplayNode *node, BOOL (^block)(ASDisplayNode *node)); +extern id ASDisplayNodeFind(ASDisplayNode * _Nullable node, BOOL (^block)(ASDisplayNode *node)); /** Given a display node, traverses up the layer tree hierarchy, returning the first display node of kind class. @@ -35,29 +37,29 @@ extern id ASDisplayNodeFind(ASDisplayNode *node, BOOL (^block)(ASDisplayNode *no extern id ASDisplayNodeFindClass(ASDisplayNode *start, Class c); /** - Given a display node, collects all descendents. This is a specialization of ASCollectContainer() that walks the Core Animation layer tree as opposed to the display node tree, thus supporting non-continues display node hierarchies. + Given a display node, collects all descendents. This is a specialization of ASCollectContainer() that walks the Core Animation layer tree as opposed to the display node tree, thus supporting non-continuous display node hierarchies. */ -extern NSArray *ASCollectDisplayNodes(ASDisplayNode *node); +extern NSArray *ASCollectDisplayNodes(ASDisplayNode *node); /** Given a display node, traverses down the node hierarchy, returning all the display nodes that pass the block. */ -extern NSArray *ASDisplayNodeFindAllSubnodes(ASDisplayNode *start, BOOL (^block)(ASDisplayNode *node)); +extern NSArray *ASDisplayNodeFindAllSubnodes(ASDisplayNode *start, BOOL (^block)(ASDisplayNode *node)); /** Given a display node, traverses down the node hierarchy, returning all the display nodes of kind class. */ -extern NSArray *ASDisplayNodeFindAllSubnodesOfClass(ASDisplayNode *start, Class c); +extern NSArray *ASDisplayNodeFindAllSubnodesOfClass(ASDisplayNode *start, Class c); /** Given a display node, traverses down the node hierarchy, returning the depth-first display node that pass the block. */ -extern id ASDisplayNodeFindFirstSubnode(ASDisplayNode *start, BOOL (^block)(ASDisplayNode *node)); +extern __kindof ASDisplayNode * ASDisplayNodeFindFirstSubnode(ASDisplayNode *start, BOOL (^block)(ASDisplayNode *node)); /** Given a display node, traverses down the node hierarchy, returning the depth-first display node of kind class. */ -extern id ASDisplayNodeFindFirstSubnodeOfClass(ASDisplayNode *start, Class c); +extern __kindof ASDisplayNode * ASDisplayNodeFindFirstSubnodeOfClass(ASDisplayNode *start, Class c); extern UIColor *ASDisplayNodeDefaultPlaceholderColor(); extern UIColor *ASDisplayNodeDefaultTintColor(); @@ -69,3 +71,5 @@ extern void ASDisplayNodeDisableHierarchyNotifications(ASDisplayNode *node); extern void ASDisplayNodeEnableHierarchyNotifications(ASDisplayNode *node); ASDISPLAYNODE_EXTERN_C_END + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/AsyncDisplayKit/ASDisplayNodeExtras.mm b/AsyncDisplayKit/ASDisplayNodeExtras.mm index 8d2e2615..e1af9e13 100644 --- a/AsyncDisplayKit/ASDisplayNodeExtras.mm +++ b/AsyncDisplayKit/ASDisplayNodeExtras.mm @@ -54,7 +54,7 @@ static void _ASCollectDisplayNodes(NSMutableArray *array, CALayer *layer) _ASCollectDisplayNodes(array, sublayer); } -extern NSArray *ASCollectDisplayNodes(ASDisplayNode *node) +extern NSArray *ASCollectDisplayNodes(ASDisplayNode *node) { NSMutableArray *list = [NSMutableArray array]; for (CALayer *sublayer in node.layer.sublayers) { @@ -79,14 +79,14 @@ static void _ASDisplayNodeFindAllSubnodes(NSMutableArray *array, ASDisplayNode * } } -extern NSArray *ASDisplayNodeFindAllSubnodes(ASDisplayNode *start, BOOL (^block)(ASDisplayNode *node)) +extern NSArray *ASDisplayNodeFindAllSubnodes(ASDisplayNode *start, BOOL (^block)(ASDisplayNode *node)) { NSMutableArray *list = [NSMutableArray array]; _ASDisplayNodeFindAllSubnodes(list, start, block); return list; } -extern NSArray *ASDisplayNodeFindAllSubnodesOfClass(ASDisplayNode *start, Class c) +extern NSArray *ASDisplayNodeFindAllSubnodesOfClass(ASDisplayNode *start, Class c) { return ASDisplayNodeFindAllSubnodes(start, ^(ASDisplayNode *n) { return [n isKindOfClass:c]; @@ -110,12 +110,12 @@ static ASDisplayNode *_ASDisplayNodeFindFirstSubnode(ASDisplayNode *startNode, B return nil; } -extern id ASDisplayNodeFindFirstSubnode(ASDisplayNode *startNode, BOOL (^block)(ASDisplayNode *node)) +extern __kindof ASDisplayNode * ASDisplayNodeFindFirstSubnode(ASDisplayNode *startNode, BOOL (^block)(ASDisplayNode *node)) { return _ASDisplayNodeFindFirstSubnode(startNode, NO, block); } -extern id ASDisplayNodeFindFirstSubnodeOfClass(ASDisplayNode *start, Class c) +extern __kindof ASDisplayNode * ASDisplayNodeFindFirstSubnodeOfClass(ASDisplayNode *start, Class c) { return ASDisplayNodeFindFirstSubnode(start, ^(ASDisplayNode *n) { return [n isKindOfClass:c]; diff --git a/AsyncDisplayKit/ASEditableTextNode.h b/AsyncDisplayKit/ASEditableTextNode.h index e343b4b4..232fd8ec 100644 --- a/AsyncDisplayKit/ASEditableTextNode.h +++ b/AsyncDisplayKit/ASEditableTextNode.h @@ -8,6 +8,7 @@ #import +NS_ASSUME_NONNULL_BEGIN @protocol ASEditableTextNodeDelegate; @@ -26,7 +27,7 @@ @property (nonatomic, readonly, strong) UITextView *textView; //! @abstract The attributes to apply to new text being entered by the user. -@property (nonatomic, readwrite, strong) NSDictionary *typingAttributes; +@property (nonatomic, readwrite, strong) NSDictionary *typingAttributes; //! @abstract The range of text currently selected. If length is zero, the range is the cursor location. @property (nonatomic, readwrite, assign) NSRange selectedRange; @@ -136,3 +137,5 @@ @end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/AsyncDisplayKit/ASImageNode.h b/AsyncDisplayKit/ASImageNode.h index 8f71a066..961da075 100644 --- a/AsyncDisplayKit/ASImageNode.h +++ b/AsyncDisplayKit/ASImageNode.h @@ -8,6 +8,7 @@ #import +NS_ASSUME_NONNULL_BEGIN /** * Image modification block. Use to transform an image before display. @@ -32,12 +33,12 @@ typedef UIImage *(^asimagenode_modification_block_t)(UIImage *image); * the layer's contentsCenter property. Non-stretchable images work too, of * course. */ -@property (atomic, retain) UIImage *image; +@property (nullable, atomic, retain) UIImage *image; /** @abstract The placeholder color. */ -@property (nonatomic, strong) UIColor *placeholderColor; +@property (nullable, nonatomic, strong) UIColor *placeholderColor; /** * @abstract Indicates whether efficient cropping of the receiver is enabled. @@ -99,7 +100,7 @@ typedef UIImage *(^asimagenode_modification_block_t)(UIImage *image); * `displaySuspended` is YES, `displayCompletionBlock` is will be * performed immediately and `YES` will be passed for `canceled`. */ -- (void)setNeedsDisplayWithCompletion:(void (^)(BOOL canceled))displayCompletionBlock; +- (void)setNeedsDisplayWithCompletion:(void (^ _Nullable)(BOOL canceled))displayCompletionBlock; @end @@ -131,3 +132,4 @@ asimagenode_modification_block_t ASImageNodeRoundBorderModificationBlock(CGFloat asimagenode_modification_block_t ASImageNodeTintColorModificationBlock(UIColor *color); ASDISPLAYNODE_EXTERN_C_END +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASImageNode.mm b/AsyncDisplayKit/ASImageNode.mm index dce8d0f0..48bd06aa 100644 --- a/AsyncDisplayKit/ASImageNode.mm +++ b/AsyncDisplayKit/ASImageNode.mm @@ -260,7 +260,7 @@ } #pragma mark - -- (void)setNeedsDisplayWithCompletion:(void (^)(BOOL canceled))displayCompletionBlock +- (void)setNeedsDisplayWithCompletion:(void (^ _Nullable)(BOOL canceled))displayCompletionBlock { if (self.displaySuspended) { if (displayCompletionBlock) diff --git a/AsyncDisplayKit/ASMultiplexImageNode.h b/AsyncDisplayKit/ASMultiplexImageNode.h index db10daa3..4ee7c7f1 100644 --- a/AsyncDisplayKit/ASMultiplexImageNode.h +++ b/AsyncDisplayKit/ASMultiplexImageNode.h @@ -9,10 +9,13 @@ #import #import +NS_ASSUME_NONNULL_BEGIN @protocol ASMultiplexImageNodeDelegate; @protocol ASMultiplexImageNodeDataSource; +typedef __kindof NSObject * ImageIdentifier; + extern NSString *const ASMultiplexImageNodeErrorDomain; /** @@ -77,7 +80,7 @@ typedef NS_ENUM(NSUInteger, ASMultiplexImageNodeErrorCode) { * * @see for more information on the image loading process. */ -@property (nonatomic, readwrite, copy) NSArray *imageIdentifiers; +@property (nonatomic, readwrite, copy) NSArray *imageIdentifiers; /** * @abstract Notify the receiver that its data source has new UIImages or NSURLs available for . @@ -91,12 +94,12 @@ typedef NS_ENUM(NSUInteger, ASMultiplexImageNodeErrorCode) { * * @discussion This value may differ from if the image hasn't yet been displayed. */ -@property (nonatomic, readonly) id loadedImageIdentifier; +@property (nullable, nonatomic, readonly) ImageIdentifier loadedImageIdentifier; /** * @abstract The identifier for the image that the receiver is currently displaying, or nil. */ -@property (nonatomic, readonly) id displayedImageIdentifier; +@property (nullable, nonatomic, readonly) ImageIdentifier displayedImageIdentifier; @end @@ -124,7 +127,7 @@ typedef NS_ENUM(NSUInteger, ASMultiplexImageNodeErrorCode) { */ - (void)multiplexImageNode:(ASMultiplexImageNode *)imageNode didUpdateDownloadProgress:(CGFloat)downloadProgress - forImageWithIdentifier:(id)imageIdentifier; + forImageWithIdentifier:(ImageIdentifier)imageIdentifier; /** * @abstract Notification that the image node's download has finished. @@ -133,8 +136,8 @@ typedef NS_ENUM(NSUInteger, ASMultiplexImageNodeErrorCode) { * @param error The error that occurred while downloading, if one occurred; nil otherwise. */ - (void)multiplexImageNode:(ASMultiplexImageNode *)imageNode -didFinishDownloadingImageWithIdentifier:(id)imageIdentifier - error:(NSError *)error; +didFinishDownloadingImageWithIdentifier:(ImageIdentifier)imageIdentifier + error:(nullable NSError *)error; /** * @abstract Notification that the image node's image was updated. @@ -147,10 +150,10 @@ didFinishDownloadingImageWithIdentifier:(id)imageIdentifier * @see <[ASMultiplexImageNodeDelegate multiplexImageNode:didDisplayUpdatedImage:withIdentifier:]>. */ - (void)multiplexImageNode:(ASMultiplexImageNode *)imageNode - didUpdateImage:(UIImage *)image - withIdentifier:(id)imageIdentifier - fromImage:(UIImage *)previousImage - withIdentifier:(id)previousImageIdentifier; + didUpdateImage:(nullable UIImage *)image + withIdentifier:(nullable ImageIdentifier)imageIdentifier + fromImage:(nullable UIImage *)previousImage + withIdentifier:(nullable ImageIdentifier)previousImageIdentifier; /** * @abstract Notification that the image node displayed a new image. @@ -160,8 +163,8 @@ didFinishDownloadingImageWithIdentifier:(id)imageIdentifier * @discussion This method is only called when `image` changes, and not on subsequent redisplays of the same image. */ - (void)multiplexImageNode:(ASMultiplexImageNode *)imageNode - didDisplayUpdatedImage:(UIImage *)image - withIdentifier:(id)imageIdentifier; + didDisplayUpdatedImage:(nullable UIImage *)image + withIdentifier:(nullable ImageIdentifier)imageIdentifier; /** * @abstract Notification that the image node finished displaying an image. @@ -189,7 +192,7 @@ didFinishDownloadingImageWithIdentifier:(id)imageIdentifier * URL to the image via -multiplexImageNode:URLForImageIdentifier:. * @returns A UIImage corresponding to `imageIdentifier`, or nil if none is available. */ -- (UIImage *)multiplexImageNode:(ASMultiplexImageNode *)imageNode imageForImageIdentifier:(id)imageIdentifier; +- (nullable UIImage *)multiplexImageNode:(ASMultiplexImageNode *)imageNode imageForImageIdentifier:(ImageIdentifier)imageIdentifier; /** * @abstract An image URL for the specified identifier. @@ -200,6 +203,8 @@ didFinishDownloadingImageWithIdentifier:(id)imageIdentifier * multiplexImageNode:imageForImageIdentifier:]> instead. * @returns An NSURL for the image identified by `imageIdentifier`, or nil if none is available. */ -- (NSURL *)multiplexImageNode:(ASMultiplexImageNode *)imageNode URLForImageIdentifier:(id)imageIdentifier; +- (nullable NSURL *)multiplexImageNode:(ASMultiplexImageNode *)imageNode URLForImageIdentifier:(ImageIdentifier)imageIdentifier; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASNetworkImageNode.h b/AsyncDisplayKit/ASNetworkImageNode.h index 5dc72352..b3961e10 100644 --- a/AsyncDisplayKit/ASNetworkImageNode.h +++ b/AsyncDisplayKit/ASNetworkImageNode.h @@ -9,6 +9,7 @@ #import #import +NS_ASSUME_NONNULL_BEGIN @protocol ASNetworkImageNodeDelegate; @@ -32,7 +33,7 @@ * * @returns An initialized ASNetworkImageNode. */ -- (instancetype)initWithCache:(id)cache downloader:(id)downloader; +- (instancetype)initWithCache:(nullable id)cache downloader:(id)downloader NS_DESIGNATED_INITIALIZER; /** * Convenience initialiser. @@ -49,14 +50,14 @@ /** * A placeholder image to display while the URL is loading. */ -@property (atomic, strong, readwrite) UIImage *defaultImage; +@property (nullable, atomic, strong, readwrite) UIImage *defaultImage; /** * The URL of a new image to download and display. * * @discussion Changing this property will reset the displayed image to a placeholder () while loading. */ -@property (atomic, strong, readwrite) NSURL *URL; +@property (nullable, atomic, strong, readwrite) NSURL *URL; /** * Download and display a new image. @@ -65,7 +66,7 @@ * * @param reset Whether to display a placeholder () while loading the new image. */ -- (void)setURL:(NSURL *)URL resetToDefault:(BOOL)reset; +- (void)setURL:(nullable NSURL *)URL resetToDefault:(BOOL)reset; /** * If is a local file, set this property to YES to take advantage of UIKit's image cacheing. Defaults to YES. @@ -102,3 +103,5 @@ - (void)imageNodeDidFinishDecoding:(ASNetworkImageNode *)imageNode; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASScrollNode.h b/AsyncDisplayKit/ASScrollNode.h index a53090bd..de6c5755 100644 --- a/AsyncDisplayKit/ASScrollNode.h +++ b/AsyncDisplayKit/ASScrollNode.h @@ -10,6 +10,7 @@ #import +NS_ASSUME_NONNULL_BEGIN /** * Simple node that wraps UIScrollView. @@ -22,3 +23,5 @@ @property (nonatomic, readonly, strong) UIScrollView *view; @end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/AsyncDisplayKit/ASTableView.h b/AsyncDisplayKit/ASTableView.h index ed3ecd62..3e42518b 100644 --- a/AsyncDisplayKit/ASTableView.h +++ b/AsyncDisplayKit/ASTableView.h @@ -18,6 +18,7 @@ @protocol ASTableViewDataSource; @protocol ASTableViewDelegate; +NS_ASSUME_NONNULL_BEGIN /** * Node-based table view. @@ -84,7 +85,7 @@ * the main thread. * @warning This method is substantially more expensive than UITableView's version. */ --(void)reloadDataWithCompletion:(void (^)())completion; +-(void)reloadDataWithCompletion:(void (^ _Nullable)())completion; /** * Reload everything from scratch, destroying the working range and all cached nodes. @@ -120,7 +121,7 @@ * Boolean parameter that contains the value YES if all of the related animations completed successfully or * NO if they were interrupted. This parameter may be nil. If supplied, the block is run on the main thread. */ -- (void)endUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL completed))completion; +- (void)endUpdatesAnimated:(BOOL)animated completion:(void (^ _Nullable)(BOOL completed))completion; /** * Inserts one or more sections, with an option to animate the insertion. @@ -180,7 +181,7 @@ * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation; +- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation; /** * Deletes the rows specified by an array of index paths, with an option to animate the deletion. @@ -192,7 +193,7 @@ * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation; +- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation; /** * Reloads the specified rows using a given animation effect. @@ -204,7 +205,7 @@ * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation; +- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation; /** * Moves the row at a specified location to a destination location. @@ -232,7 +233,7 @@ * * @returns an array containing the nodes being displayed on screen. */ -- (NSArray *)visibleNodes; +- (NSArray *)visibleNodes; /** * YES to automatically adjust the contentOffset when cells are inserted or deleted "before" @@ -298,7 +299,7 @@ @optional - (void)tableView:(ASTableView *)tableView willDisplayNodeForRowAtIndexPath:(NSIndexPath *)indexPath; -- (void)tableView:(ASTableView *)tableView didEndDisplayingNodeForRowAtIndexPath:(NSIndexPath*)indexPath; +- (void)tableView:(ASTableView *)tableView didEndDisplayingNodeForRowAtIndexPath:(NSIndexPath *)indexPath; /** * Receive a message that the tableView is near the end of its data set and more data should be fetched if necessary. @@ -334,3 +335,5 @@ @property (nonatomic, assign) ASRangeTuningParameters rangeTuningParameters ASDISPLAYNODE_DEPRECATED; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASTableViewProtocols.h b/AsyncDisplayKit/ASTableViewProtocols.h index 84458179..df8bb811 100644 --- a/AsyncDisplayKit/ASTableViewProtocols.h +++ b/AsyncDisplayKit/ASTableViewProtocols.h @@ -6,6 +6,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ +NS_ASSUME_NONNULL_BEGIN + /** * This is a subset of UITableViewDataSource. * @@ -21,14 +23,14 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; -- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section; +- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; +- (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section; - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath; - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath; -- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView; +- (nullable NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView; - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index; - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath; @@ -55,8 +57,8 @@ - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section; - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section; -- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section; -- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section; +- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section; +- (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section; - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath; @@ -64,14 +66,14 @@ - (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath; - (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath; -- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath; -- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath; +- (nullable NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath; +- (nullable NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath; - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath; - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath; - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath; -- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath; -- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath; +- (nullable NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath; +- (nullable NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath; - (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath; @@ -83,7 +85,9 @@ - (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath; - (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath; -- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender; -- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender; +- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender; +- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASTextNode.h b/AsyncDisplayKit/ASTextNode.h index e8d5b761..e7fdf85f 100644 --- a/AsyncDisplayKit/ASTextNode.h +++ b/AsyncDisplayKit/ASTextNode.h @@ -8,6 +8,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + @protocol ASTextNodeDelegate; /** @@ -36,7 +38,7 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) { @discussion Defaults to nil, no text is shown. For inline image attachments, add an attribute of key NSAttachmentAttributeName, with a value of an NSTextAttachment. */ -@property (nonatomic, copy) NSAttributedString *attributedString; +@property (nullable, nonatomic, copy) NSAttributedString *attributedString; #pragma mark - Truncation @@ -75,14 +77,14 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) { */ @property (nonatomic, readonly, assign) NSUInteger lineCount; -@property (nonatomic, strong) NSArray *exclusionPaths; +@property (nonatomic, strong) NSArray *exclusionPaths; #pragma mark - Placeholders /** @abstract The placeholder color. */ -@property (nonatomic, strong) UIColor *placeholderColor; +@property (nullable, nonatomic, strong) UIColor *placeholderColor; /** @abstract Inset each line of the placeholder. @@ -118,7 +120,7 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) { a line break, the rects returned will be on opposite sides and different lines). The rects returned are in the coordinate system of the receiver. */ -- (NSArray *)rectsForTextRange:(NSRange)textRange; +- (NSArray *)rectsForTextRange:(NSRange)textRange; /** @abstract Returns an array of rects used for highlighting the characters in a given text range. @@ -129,7 +131,7 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) { are in the coordinate system of the receiver. This method is useful for visual coordination with a highlighted range of text. */ -- (NSArray *)highlightRectsForTextRange:(NSRange)textRange; +- (NSArray *)highlightRectsForTextRange:(NSRange)textRange; /** @abstract Returns a bounding rect for the given text range. @@ -153,7 +155,7 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) { /** @abstract The set of attribute names to consider links. Defaults to NSLinkAttributeName. */ -@property (nonatomic, copy) NSArray *linkAttributeNames; +@property (nonatomic, copy) NSArray *linkAttributeNames; /** @abstract Indicates whether the receiver has an entity at a given point. @@ -162,7 +164,7 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) { @param rangeOut The ultimate range of the found text. Can be NULL. @result YES if an entity exists at `point`; NO otherwise. */ -- (id)linkAttributeValueAtPoint:(CGPoint)point attributeName:(out NSString **)attributeNameOut range:(out NSRange *)rangeOut; +- (nullable id)linkAttributeValueAtPoint:(CGPoint)point attributeName:(out NSString * _Nullable * _Nullable)attributeNameOut range:(out NSRange * _Nullable)rangeOut; /** @abstract The style to use when highlighting text. @@ -253,3 +255,5 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) { - (BOOL)textNode:(ASTextNode *)textNode shouldLongPressLinkAttribute:(NSString *)attribute value:(id)value atPoint:(CGPoint)point; @end + +NS_ASSUME_NONNULL_END diff --git a/examples/Swift/Sample.xcodeproj/project.pbxproj b/examples/Swift/Sample.xcodeproj/project.pbxproj index 4a845e16..4aec090c 100644 --- a/examples/Swift/Sample.xcodeproj/project.pbxproj +++ b/examples/Swift/Sample.xcodeproj/project.pbxproj @@ -128,6 +128,8 @@ 050E7C6619D22E19004363C2 /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftMigration = 0700; + LastSwiftUpdateCheck = 0700; LastUpgradeCheck = 0600; ORGANIZATIONNAME = Facebook; TargetAttributes = { diff --git a/examples/Swift/Sample/ViewController.swift b/examples/Swift/Sample/ViewController.swift index 9801a205..037e0965 100644 --- a/examples/Swift/Sample/ViewController.swift +++ b/examples/Swift/Sample/ViewController.swift @@ -27,7 +27,7 @@ class ViewController: UIViewController, ASTableViewDataSource, ASTableViewDelega self.tableView.asyncDelegate = self } - required init(coder aDecoder: NSCoder) { + required init?(coder aDecoder: NSCoder) { fatalError("storyboards are incompatible with truth and beauty") } From 262d65eea9a18e7728e282c6992911df55823ddd Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Wed, 16 Sep 2015 15:34:24 -0700 Subject: [PATCH 02/60] More updates --- AsyncDisplayKit/ASImageNode.h | 4 ++-- AsyncDisplayKit/ASMultiplexImageNode.h | 2 +- AsyncDisplayKitTests/ASDisplayNodeTests.m | 18 ------------------ .../ASLayoutSpecSnapshotTestsHelper.m | 2 +- 4 files changed, 4 insertions(+), 22 deletions(-) diff --git a/AsyncDisplayKit/ASImageNode.h b/AsyncDisplayKit/ASImageNode.h index 961da075..2afdcbda 100644 --- a/AsyncDisplayKit/ASImageNode.h +++ b/AsyncDisplayKit/ASImageNode.h @@ -17,7 +17,7 @@ NS_ASSUME_NONNULL_BEGIN * * @returns A transformed image. */ -typedef UIImage *(^asimagenode_modification_block_t)(UIImage *image); +typedef UIImage * _Nullable (^asimagenode_modification_block_t)(UIImage *image); /** @@ -86,7 +86,7 @@ typedef UIImage *(^asimagenode_modification_block_t)(UIImage *image); * @discussion Can be used to add image effects (such as rounding, adding * borders, or other pattern overlays) without extraneous display calls. */ -@property (nonatomic, readwrite, copy) asimagenode_modification_block_t imageModificationBlock; +@property (nullable, nonatomic, readwrite, copy) asimagenode_modification_block_t imageModificationBlock; /** * @abstract Marks the receiver as needing display and performs a block after diff --git a/AsyncDisplayKit/ASMultiplexImageNode.h b/AsyncDisplayKit/ASMultiplexImageNode.h index 4ee7c7f1..027d9b3d 100644 --- a/AsyncDisplayKit/ASMultiplexImageNode.h +++ b/AsyncDisplayKit/ASMultiplexImageNode.h @@ -50,7 +50,7 @@ typedef NS_ENUM(NSUInteger, ASMultiplexImageNodeErrorCode) { * @discussion If `cache` is nil, the receiver will not attempt to retrieve images from a cache before downloading them. * @returns An initialized ASMultiplexImageNode. */ -- (instancetype)initWithCache:(id)cache downloader:(id)downloader NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithCache:(nullable id)cache downloader:(nullable id)downloader NS_DESIGNATED_INITIALIZER; /** * @abstract The delegate, which must conform to the protocol. diff --git a/AsyncDisplayKitTests/ASDisplayNodeTests.m b/AsyncDisplayKitTests/ASDisplayNodeTests.m index 4ce0c49b..cd0b273f 100644 --- a/AsyncDisplayKitTests/ASDisplayNodeTests.m +++ b/AsyncDisplayKitTests/ASDisplayNodeTests.m @@ -1042,7 +1042,6 @@ static inline BOOL _CGPointEqualToPointWithEpsilon(CGPoint point1, CGPoint point - (void)testSubnodes { ASDisplayNode *parent = [[ASDisplayNode alloc] init]; - XCTAssertNoThrow([parent addSubnode:nil], @"Don't try to add nil, but we'll deal."); XCTAssertNoThrow([parent addSubnode:parent], @"Not good, test that we recover"); XCTAssertEqual(0u, parent.subnodes.count, @"We shouldn't have any subnodes"); } @@ -1456,15 +1455,9 @@ static inline BOOL _CGPointEqualToPointWithEpsilon(CGPoint point1, CGPoint point XCTAssertNodeSubnodeSubviewSublayerOrder(parent, loaded, isLayerBacked, @"c,a,b", @"Incorrect insertion below"); XCTAssertNodesHaveParent(parent, a, b, c); - // Check insertSubnode with no below - XCTAssertThrows([parent insertSubnode:b belowSubnode:nil], @"Can't insert below a nil"); // Check nothing was inserted XCTAssertNodeSubnodeSubviewSublayerOrder(parent, loaded, isLayerBacked, @"c,a,b", @"Incorrect insertion below"); - - XCTAssertThrows([parent insertSubnode:nil belowSubnode:nil], @"Can't insert a nil subnode"); - XCTAssertThrows([parent insertSubnode:nil belowSubnode:a], @"Can't insert a nil subnode"); - // Check inserting below when you're already in the array // (c,a,b) => (a,c,b) [parent insertSubnode:c belowSubnode:b]; @@ -1535,17 +1528,6 @@ static inline BOOL _CGPointEqualToPointWithEpsilon(CGPoint point1, CGPoint point [parent insertSubnode:c aboveSubnode:a]; XCTAssertNodeSubnodeSubviewSublayerOrder(parent, loaded, isLayerBacked, @"a,c,b", @"After insert c above a"); - // Check insertSubnode with invalid parameters throws and doesn't change anything - // (a,c,b) => (a,c,b) - XCTAssertThrows([parent insertSubnode:b aboveSubnode:nil], @"Can't insert below a nil"); - XCTAssertNodeSubnodeSubviewSublayerOrder(parent, loaded, isLayerBacked, @"a,c,b", @"Check no monkey business"); - - XCTAssertThrows([parent insertSubnode:nil aboveSubnode:nil], @"Can't insert a nil subnode"); - XCTAssertNodeSubnodeSubviewSublayerOrder(parent, loaded, isLayerBacked, @"a,c,b", @"Check no monkey business"); - - XCTAssertThrows([parent insertSubnode:nil aboveSubnode:a], @"Can't insert a nil subnode"); - XCTAssertNodeSubnodeSubviewSublayerOrder(parent, loaded, isLayerBacked, @"a,c,b", @"Check no monkey business"); - // Check inserting above when you're already in the array // (a,c,b) => (c,b,a) [parent insertSubnode:a aboveSubnode:b]; diff --git a/AsyncDisplayKitTests/ASLayoutSpecSnapshotTestsHelper.m b/AsyncDisplayKitTests/ASLayoutSpecSnapshotTestsHelper.m index 4cd9232f..92895d5a 100644 --- a/AsyncDisplayKitTests/ASLayoutSpecSnapshotTestsHelper.m +++ b/AsyncDisplayKitTests/ASLayoutSpecSnapshotTestsHelper.m @@ -57,7 +57,7 @@ layout.position = CGPointZero; layout = [ASLayout layoutWithLayoutableObject:self size:layout.size sublayouts:@[layout]]; _layoutUnderTest = [layout flattenedLayoutUsingPredicateBlock:^BOOL(ASLayout *evaluatedLayout) { - return [self.subnodes containsObject:evaluatedLayout.layoutableObject]; + return [self.subnodes containsObject:(ASDisplayNode *)evaluatedLayout.layoutableObject]; }]; self.frame = CGRectMake(0, 0, _layoutUnderTest.size.width, _layoutUnderTest.size.height); [self measure:_layoutUnderTest.size]; From 04690c0a4c8a6450b6e5e69f532588700da6a4d9 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Wed, 16 Sep 2015 15:36:52 -0700 Subject: [PATCH 03/60] Re-add nil tests --- AsyncDisplayKitTests/ASDisplayNodeTests.m | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/AsyncDisplayKitTests/ASDisplayNodeTests.m b/AsyncDisplayKitTests/ASDisplayNodeTests.m index cd0b273f..75adeee1 100644 --- a/AsyncDisplayKitTests/ASDisplayNodeTests.m +++ b/AsyncDisplayKitTests/ASDisplayNodeTests.m @@ -1042,6 +1042,8 @@ static inline BOOL _CGPointEqualToPointWithEpsilon(CGPoint point1, CGPoint point - (void)testSubnodes { ASDisplayNode *parent = [[ASDisplayNode alloc] init]; + ASDisplayNode *nilNode = nil; + XCTAssertNoThrow([parent addSubnode:nilNode], @"Don't try to add nil, but we'll deal."); XCTAssertNoThrow([parent addSubnode:parent], @"Not good, test that we recover"); XCTAssertEqual(0u, parent.subnodes.count, @"We shouldn't have any subnodes"); } @@ -1455,9 +1457,16 @@ static inline BOOL _CGPointEqualToPointWithEpsilon(CGPoint point1, CGPoint point XCTAssertNodeSubnodeSubviewSublayerOrder(parent, loaded, isLayerBacked, @"c,a,b", @"Incorrect insertion below"); XCTAssertNodesHaveParent(parent, a, b, c); + // Check insertSubnode with no below + ASDisplayNode *nilNode = nil; + XCTAssertThrows([parent insertSubnode:b belowSubnode:nilNode], @"Can't insert below a nil"); // Check nothing was inserted XCTAssertNodeSubnodeSubviewSublayerOrder(parent, loaded, isLayerBacked, @"c,a,b", @"Incorrect insertion below"); + + XCTAssertThrows([parent insertSubnode:nilNode belowSubnode:nilNode], @"Can't insert a nil subnode"); + XCTAssertThrows([parent insertSubnode:nilNode belowSubnode:a], @"Can't insert a nil subnode"); + // Check inserting below when you're already in the array // (c,a,b) => (a,c,b) [parent insertSubnode:c belowSubnode:b]; @@ -1528,6 +1537,18 @@ static inline BOOL _CGPointEqualToPointWithEpsilon(CGPoint point1, CGPoint point [parent insertSubnode:c aboveSubnode:a]; XCTAssertNodeSubnodeSubviewSublayerOrder(parent, loaded, isLayerBacked, @"a,c,b", @"After insert c above a"); + // Check insertSubnode with invalid parameters throws and doesn't change anything + // (a,c,b) => (a,c,b) + ASDisplayNode *nilNode = nil; + XCTAssertThrows([parent insertSubnode:b aboveSubnode:nilNode], @"Can't insert below a nil"); + XCTAssertNodeSubnodeSubviewSublayerOrder(parent, loaded, isLayerBacked, @"a,c,b", @"Check no monkey business"); + + XCTAssertThrows([parent insertSubnode:nilNode aboveSubnode:nilNode], @"Can't insert a nil subnode"); + XCTAssertNodeSubnodeSubviewSublayerOrder(parent, loaded, isLayerBacked, @"a,c,b", @"Check no monkey business"); + + XCTAssertThrows([parent insertSubnode:nilNode aboveSubnode:a], @"Can't insert a nil subnode"); + XCTAssertNodeSubnodeSubviewSublayerOrder(parent, loaded, isLayerBacked, @"a,c,b", @"Check no monkey business"); + // Check inserting above when you're already in the array // (a,c,b) => (c,b,a) [parent insertSubnode:a aboveSubnode:b]; From 30ed0bd64ae09754ca3cc57491aef2742cdbaac2 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Wed, 16 Sep 2015 15:39:06 -0700 Subject: [PATCH 04/60] Restore old ASCollectionNode init --- AsyncDisplayKit/ASCollectionNode.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AsyncDisplayKit/ASCollectionNode.m b/AsyncDisplayKit/ASCollectionNode.m index 29332897..315992a4 100644 --- a/AsyncDisplayKit/ASCollectionNode.m +++ b/AsyncDisplayKit/ASCollectionNode.m @@ -13,7 +13,8 @@ - (instancetype)init { ASDISPLAYNODE_NOT_DESIGNATED_INITIALIZER(); - self = [self initWithCollectionViewLayout:[UICollectionViewFlowLayout new]]; + UICollectionViewLayout *nilLayout = nil; + self = [self initWithCollectionViewLayout:nilLayout]; // Will throw an exception for lacking a UICV Layout. return nil; } From a7240bac275aee897f1ed7f9ec62380c7b3053b3 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Wed, 16 Sep 2015 15:41:56 -0700 Subject: [PATCH 05/60] More objective-C cleanup --- AsyncDisplayKit/ASCellNode.h | 2 +- AsyncDisplayKit/ASCollectionNode.h | 2 +- AsyncDisplayKit/ASDisplayNode.h | 6 +++--- AsyncDisplayKit/ASDisplayNodeExtras.h | 2 +- AsyncDisplayKit/ASEditableTextNode.h | 2 +- AsyncDisplayKit/ASScrollNode.h | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/AsyncDisplayKit/ASCellNode.h b/AsyncDisplayKit/ASCellNode.h index 380eddbe..32e24be6 100644 --- a/AsyncDisplayKit/ASCellNode.h +++ b/AsyncDisplayKit/ASCellNode.h @@ -45,4 +45,4 @@ NS_ASSUME_NONNULL_BEGIN @end -NS_ASSUME_NONNULL_END \ No newline at end of file +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASCollectionNode.h b/AsyncDisplayKit/ASCollectionNode.h index 46301402..8292280a 100644 --- a/AsyncDisplayKit/ASCollectionNode.h +++ b/AsyncDisplayKit/ASCollectionNode.h @@ -22,4 +22,4 @@ NS_ASSUME_NONNULL_BEGIN @end -NS_ASSUME_NONNULL_END \ No newline at end of file +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index 0cfdae93..7412a497 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -585,7 +585,7 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); @property (atomic, assign) CGFloat contentsScale; // default=1.0f. See @contentsScaleForDisplay for more info @property (atomic, assign) CATransform3D transform; // default=CATransform3DIdentity @property (atomic, assign) CATransform3D subnodeTransform; // default=CATransform3DIdentity -@property (atomic, copy, nullable) NSString *name; // default=nil. Use this to tag your layers in the server-recurse-description / pca or for your own purposes +@property (atomic, copy, nullable) NSString *name; // default=nil. Use this to tag your layers in the server-recurse-description / pca or for your own purposes /** * @abstract The node view's background color. @@ -593,9 +593,9 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); * @discussion In contrast to UIView, setting a transparent color will not set opaque = NO. * This only affects nodes that implement +drawRect like ASTextNode. */ -@property (atomic, retain, nullable) UIColor *backgroundColor; // default=nil +@property (atomic, retain, nullable) UIColor *backgroundColor; // default=nil -@property (atomic, retain, null_resettable) UIColor *tintColor; // default=Blue +@property (atomic, retain, null_resettable) UIColor *tintColor; // default=Blue - (void)tintColorDidChange; // Notifies the node when the tintColor has changed. /** diff --git a/AsyncDisplayKit/ASDisplayNodeExtras.h b/AsyncDisplayKit/ASDisplayNodeExtras.h index 521dce25..060cadcc 100644 --- a/AsyncDisplayKit/ASDisplayNodeExtras.h +++ b/AsyncDisplayKit/ASDisplayNodeExtras.h @@ -72,4 +72,4 @@ extern void ASDisplayNodeEnableHierarchyNotifications(ASDisplayNode *node); ASDISPLAYNODE_EXTERN_C_END -NS_ASSUME_NONNULL_END \ No newline at end of file +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASEditableTextNode.h b/AsyncDisplayKit/ASEditableTextNode.h index 232fd8ec..6c4b4582 100644 --- a/AsyncDisplayKit/ASEditableTextNode.h +++ b/AsyncDisplayKit/ASEditableTextNode.h @@ -138,4 +138,4 @@ NS_ASSUME_NONNULL_BEGIN @end -NS_ASSUME_NONNULL_END \ No newline at end of file +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASScrollNode.h b/AsyncDisplayKit/ASScrollNode.h index de6c5755..32733ffe 100644 --- a/AsyncDisplayKit/ASScrollNode.h +++ b/AsyncDisplayKit/ASScrollNode.h @@ -24,4 +24,4 @@ NS_ASSUME_NONNULL_BEGIN @end -NS_ASSUME_NONNULL_END \ No newline at end of file +NS_ASSUME_NONNULL_END From e4dc823c0dfa63c45a6aa8bebfc68cf3bbadeeec Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Wed, 16 Sep 2015 16:21:07 -0700 Subject: [PATCH 06/60] hitTest:withEvent: return value should be nullable --- AsyncDisplayKit/ASControlNode+Subclasses.h | 2 +- AsyncDisplayKit/ASDisplayNode+Subclasses.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AsyncDisplayKit/ASControlNode+Subclasses.h b/AsyncDisplayKit/ASControlNode+Subclasses.h index 90c5f68e..085eb9bb 100644 --- a/AsyncDisplayKit/ASControlNode+Subclasses.h +++ b/AsyncDisplayKit/ASControlNode+Subclasses.h @@ -63,4 +63,4 @@ NS_ASSUME_NONNULL_BEGIN @end -NS_ASSUME_NONNULL_END \ No newline at end of file +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASDisplayNode+Subclasses.h b/AsyncDisplayKit/ASDisplayNode+Subclasses.h index 5814376d..3ecd08e1 100644 --- a/AsyncDisplayKit/ASDisplayNode+Subclasses.h +++ b/AsyncDisplayKit/ASDisplayNode+Subclasses.h @@ -361,7 +361,7 @@ NS_ASSUME_NONNULL_BEGIN * 1) allows sending events to plain UIViews that don't have attached nodes, * 2) hitTest: is never called before the views are created. */ -- (UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event; +- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event; /** @name Observing node-related changes */ From 6bcd245c6db43865d24fbb2808a7704d72c9a26d Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Wed, 16 Sep 2015 17:03:33 -0700 Subject: [PATCH 07/60] Bump the .travis.yml OS X image requirement for Xcode 7 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 35dc2d00..4d09065e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: objective-c +osx_image: xcode7 before_install: - brew update - brew reinstall xctool From 717df1cfd2681c0660d802e40f2d4625b7c5f614 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Thu, 17 Sep 2015 11:39:59 -0700 Subject: [PATCH 08/60] Merge latest master and update Layout headers --- AsyncDisplayKit/ASViewController.h | 5 ++++- AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.h | 13 ++++++++----- AsyncDisplayKit/Layout/ASCenterLayoutSpec.h | 4 ++++ AsyncDisplayKit/Layout/ASDimension.h | 2 ++ AsyncDisplayKit/Layout/ASInsetLayoutSpec.h | 6 +++++- AsyncDisplayKit/Layout/ASLayout.h | 10 +++++++--- AsyncDisplayKit/Layout/ASLayoutOptions.h | 7 ++++++- AsyncDisplayKit/Layout/ASLayoutSpec.h | 13 +++++++++---- AsyncDisplayKit/Layout/ASLayoutable.h | 4 ++++ AsyncDisplayKit/Layout/ASOverlayLayoutSpec.h | 8 ++++++-- AsyncDisplayKit/Layout/ASRatioLayoutSpec.h | 4 ++++ AsyncDisplayKit/Layout/ASRelativeSize.h | 2 ++ AsyncDisplayKit/Layout/ASStackLayoutSpec.h | 5 ++++- AsyncDisplayKit/Layout/ASStackLayoutable.h | 4 ++++ AsyncDisplayKit/Layout/ASStaticLayoutSpec.h | 6 +++++- AsyncDisplayKit/Layout/ASStaticLayoutable.h | 4 ++++ 16 files changed, 78 insertions(+), 19 deletions(-) diff --git a/AsyncDisplayKit/ASViewController.h b/AsyncDisplayKit/ASViewController.h index e3b18661..aca6626f 100644 --- a/AsyncDisplayKit/ASViewController.h +++ b/AsyncDisplayKit/ASViewController.h @@ -9,11 +9,14 @@ #import #import +NS_ASSUME_NONNULL_BEGIN + @interface ASViewController : UIViewController @property (nonatomic, strong, readonly) ASDisplayNode *node; -//TODO Use nonnull annotation late on. Travis doesn't recognize it (yet). - (instancetype)initWithNode:(ASDisplayNode *)node; @end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.h b/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.h index cab51ea8..9f04490c 100644 --- a/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.h @@ -10,18 +10,21 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** Lays out a single layoutable child, then lays out a background layoutable instance behind it stretched to its size. */ @interface ASBackgroundLayoutSpec : ASLayoutSpec -@property (nonatomic, strong) id background; +@property (nullable, nonatomic, strong) id background; /** - @param child A child that is laid out to determine the size of this spec. If this is nil, then this method - returns nil. - @param background A layoutable object that is laid out behind the child. May be nil, in which case the background is omitted. + @param child A child that is laid out to determine the size of this spec. + @param background A layoutable object that is laid out behind the child. If this is nil, the background is omitted. */ -+ (instancetype)backgroundLayoutSpecWithChild:(id)child background:(id)background; ++ (instancetype)backgroundLayoutSpecWithChild:(id)child background:(nullable id)background; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Layout/ASCenterLayoutSpec.h b/AsyncDisplayKit/Layout/ASCenterLayoutSpec.h index 37ba24e7..f8413d27 100644 --- a/AsyncDisplayKit/Layout/ASCenterLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASCenterLayoutSpec.h @@ -34,6 +34,8 @@ typedef NS_OPTIONS(NSUInteger, ASCenterLayoutSpecSizingOptions) { ASCenterLayoutSpecSizingOptionMinimumXY = ASCenterLayoutSpecSizingOptionMinimumX | ASCenterLayoutSpecSizingOptionMinimumY, }; +NS_ASSUME_NONNULL_BEGIN + /** Lays out a single layoutable child and position it so that it is centered into the layout bounds. */ @interface ASCenterLayoutSpec : ASLayoutSpec @@ -54,3 +56,5 @@ typedef NS_OPTIONS(NSUInteger, ASCenterLayoutSpecSizingOptions) { child:(id)child; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Layout/ASDimension.h b/AsyncDisplayKit/Layout/ASDimension.h index 590f9486..c96b2155 100644 --- a/AsyncDisplayKit/Layout/ASDimension.h +++ b/AsyncDisplayKit/Layout/ASDimension.h @@ -35,6 +35,7 @@ typedef struct { extern ASRelativeDimension const ASRelativeDimensionUnconstrained; ASDISPLAYNODE_EXTERN_C_BEGIN +NS_ASSUME_NONNULL_BEGIN #pragma mark ASRelativeDimension @@ -70,4 +71,5 @@ extern BOOL ASSizeRangeEqualToSizeRange(ASSizeRange lhs, ASSizeRange rhs); extern NSString *NSStringFromASSizeRange(ASSizeRange sizeRange); +NS_ASSUME_NONNULL_END ASDISPLAYNODE_EXTERN_C_END diff --git a/AsyncDisplayKit/Layout/ASInsetLayoutSpec.h b/AsyncDisplayKit/Layout/ASInsetLayoutSpec.h index ab0a6f10..aa320e94 100644 --- a/AsyncDisplayKit/Layout/ASInsetLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASInsetLayoutSpec.h @@ -10,6 +10,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** A layout spec that wraps another layoutable child, applying insets around it. @@ -33,8 +35,10 @@ /** @param insets The amount of space to inset on each side. - @param child The wrapped child to inset. If nil, this method returns nil. + @param child The wrapped child to inset. */ + (instancetype)insetLayoutSpecWithInsets:(UIEdgeInsets)insets child:(id)child; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Layout/ASLayout.h b/AsyncDisplayKit/Layout/ASLayout.h index 71892b59..4619269d 100644 --- a/AsyncDisplayKit/Layout/ASLayout.h +++ b/AsyncDisplayKit/Layout/ASLayout.h @@ -12,6 +12,8 @@ #import #import +NS_ASSUME_NONNULL_BEGIN + extern CGPoint const CGPointNull; extern BOOL CGPointIsNull(CGPoint point); @@ -30,7 +32,7 @@ extern BOOL CGPointIsNull(CGPoint point); /** * Array of ASLayouts. Each must have a valid non-null position. */ -@property (nonatomic, readonly) NSArray *sublayouts; +@property (nonatomic, readonly) NSArray *sublayouts; /** * Initializer. @@ -46,7 +48,7 @@ extern BOOL CGPointIsNull(CGPoint point); + (instancetype)layoutWithLayoutableObject:(id)layoutableObject size:(CGSize)size position:(CGPoint)position - sublayouts:(NSArray *)sublayouts; + sublayouts:(nullable NSArray *)sublayouts; /** * Convenience initializer that has CGPointNull position. @@ -62,7 +64,7 @@ extern BOOL CGPointIsNull(CGPoint point); */ + (instancetype)layoutWithLayoutableObject:(id)layoutableObject size:(CGSize)size - sublayouts:(NSArray *)sublayouts; + sublayouts:(nullable NSArray *)sublayouts; /** * Convenience that has CGPointNull position and no sublayouts. @@ -89,3 +91,5 @@ extern BOOL CGPointIsNull(CGPoint point); - (ASLayout *)flattenedLayoutUsingPredicateBlock:(BOOL (^)(ASLayout *evaluatedLayout))predicateBlock; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Layout/ASLayoutOptions.h b/AsyncDisplayKit/Layout/ASLayoutOptions.h index 7b9800ff..799f3e6b 100644 --- a/AsyncDisplayKit/Layout/ASLayoutOptions.h +++ b/AsyncDisplayKit/Layout/ASLayoutOptions.h @@ -11,6 +11,8 @@ #import #import +NS_ASSUME_NONNULL_BEGIN + @protocol ASLayoutable; /** @@ -52,7 +54,7 @@ * * @return a new instance of ASLayoutOptions */ -- (instancetype)initWithLayoutable:(id)layoutable; +- (instancetype)initWithLayoutable:(id)layoutable NS_DESIGNATED_INITIALIZER; /** * Copies the values of layoutOptions into self. This is useful when placing a layoutable inside of another. Consider @@ -83,3 +85,6 @@ @property (nonatomic, readwrite) CGPoint layoutPosition; @end + +NS_ASSUME_NONNULL_END + diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.h b/AsyncDisplayKit/Layout/ASLayoutSpec.h index 2dd00198..15dda10c 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.h @@ -10,6 +10,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** A layout spec is an immutable object that describes a layout, loosely inspired by React. */ @interface ASLayoutSpec : NSObject @@ -69,7 +71,7 @@ * For good measure, in these layout specs it probably makes sense to define * setChild: and setChild:forIdentifier: methods to do something appropriate or to assert. */ -- (void)setChildren:(NSArray *)children; +- (void)setChildren:(NSArray> *)children; /** * Get child methods @@ -83,16 +85,19 @@ */ /** Returns the child added to this layout spec using the default identifier. */ -- (id)child; +- (nullable id)child; /** * Returns the child added to this layout spec using the given identifier. * * @param identifier An identifier associated withe the child. */ -- (id)childForIdentifier:(NSString *)identifier; +- (nullable id)childForIdentifier:(NSString *)identifier; /** Returns all children added to this layout spec. */ -- (NSArray *)children; +- (NSArray> *)children; @end + +NS_ASSUME_NONNULL_END + diff --git a/AsyncDisplayKit/Layout/ASLayoutable.h b/AsyncDisplayKit/Layout/ASLayoutable.h index 7e0e950d..4653e38d 100644 --- a/AsyncDisplayKit/Layout/ASLayoutable.h +++ b/AsyncDisplayKit/Layout/ASLayoutable.h @@ -19,6 +19,8 @@ @class ASLayout; @class ASLayoutSpec; +NS_ASSUME_NONNULL_BEGIN + /** * The ASLayoutable protocol declares a method for measuring the layout of an object. A layout * is defined by an ASLayout return value, and must specify 1) the size (but not position) of the @@ -107,3 +109,5 @@ @property (nonatomic, assign) CGPoint layoutPosition; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.h b/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.h index 05e53d92..6e1c321b 100644 --- a/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.h @@ -10,13 +10,17 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** This layout spec lays out a single layoutable child and then overlays a layoutable object on top of it streched to its size */ @interface ASOverlayLayoutSpec : ASLayoutSpec -@property (nonatomic, strong) id overlay; +@property (nullable, nonatomic, strong) id overlay; -+ (instancetype)overlayLayoutSpecWithChild:(id)child overlay:(id)overlay; ++ (instancetype)overlayLayoutSpecWithChild:(id)child overlay:(nullable id)overlay; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.h b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.h index 2affa56a..f9109829 100644 --- a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.h @@ -11,6 +11,8 @@ #import #import +NS_ASSUME_NONNULL_BEGIN + /** Ratio layout spec For when the content should respect a certain inherent ratio but can be scaled (think photos or videos) @@ -36,3 +38,5 @@ + (instancetype)ratioLayoutSpecWithRatio:(CGFloat)ratio child:(id)child; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Layout/ASRelativeSize.h b/AsyncDisplayKit/Layout/ASRelativeSize.h index 9522d43d..db5d662a 100644 --- a/AsyncDisplayKit/Layout/ASRelativeSize.h +++ b/AsyncDisplayKit/Layout/ASRelativeSize.h @@ -33,6 +33,7 @@ typedef struct { extern ASRelativeSizeRange const ASRelativeSizeRangeUnconstrained; ASDISPLAYNODE_EXTERN_C_BEGIN +NS_ASSUME_NONNULL_BEGIN #pragma mark - #pragma mark ASRelativeSize @@ -70,4 +71,5 @@ extern BOOL ASRelativeSizeRangeEqualToRelativeSizeRange(ASRelativeSizeRange lhs, extern ASSizeRange ASRelativeSizeRangeResolve(ASRelativeSizeRange relativeSizeRange, CGSize parentSize); +NS_ASSUME_NONNULL_END ASDISPLAYNODE_EXTERN_C_END diff --git a/AsyncDisplayKit/Layout/ASStackLayoutSpec.h b/AsyncDisplayKit/Layout/ASStackLayoutSpec.h index dd331f14..d6aa54b1 100644 --- a/AsyncDisplayKit/Layout/ASStackLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASStackLayoutSpec.h @@ -11,6 +11,7 @@ #import #import +NS_ASSUME_NONNULL_BEGIN /** A simple layout spec that stacks a list of children vertically or horizontally. @@ -55,6 +56,8 @@ @param alignItems Orientation of the children along the cross axis @param children ASLayoutable children to be positioned. */ -+ (instancetype)stackLayoutSpecWithDirection:(ASStackLayoutDirection)direction spacing:(CGFloat)spacing justifyContent:(ASStackLayoutJustifyContent)justifyContent alignItems:(ASStackLayoutAlignItems)alignItems children:(NSArray *)children; ++ (instancetype)stackLayoutSpecWithDirection:(ASStackLayoutDirection)direction spacing:(CGFloat)spacing justifyContent:(ASStackLayoutJustifyContent)justifyContent alignItems:(ASStackLayoutAlignItems)alignItems children:(NSArray> *)children; @end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/AsyncDisplayKit/Layout/ASStackLayoutable.h b/AsyncDisplayKit/Layout/ASStackLayoutable.h index 3ebc9304..9044a275 100644 --- a/AsyncDisplayKit/Layout/ASStackLayoutable.h +++ b/AsyncDisplayKit/Layout/ASStackLayoutable.h @@ -11,6 +11,8 @@ #import #import +NS_ASSUME_NONNULL_BEGIN + /** * Layout options that can be defined for an ASLayoutable being added to a ASStackLayoutSpec. */ @@ -64,3 +66,5 @@ @property (nonatomic, readwrite) CGFloat descender; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.h b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.h index 8bd3f3d9..44da4adf 100644 --- a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.h @@ -11,6 +11,8 @@ #import #import +NS_ASSUME_NONNULL_BEGIN + /** * A layout spec that positions children at fixed positions. * @@ -21,6 +23,8 @@ /** @param children Children to be positioned at fixed positions, each conforms to ASStaticLayoutable */ -+ (instancetype)staticLayoutSpecWithChildren:(NSArray *)children; ++ (instancetype)staticLayoutSpecWithChildren:(NSArray> *)children; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Layout/ASStaticLayoutable.h b/AsyncDisplayKit/Layout/ASStaticLayoutable.h index e0325cfc..8e5f6e62 100644 --- a/AsyncDisplayKit/Layout/ASStaticLayoutable.h +++ b/AsyncDisplayKit/Layout/ASStaticLayoutable.h @@ -10,6 +10,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** * Layout options that can be defined for an ASLayoutable being added to a ASStaticLayoutSpec. */ @@ -24,3 +26,5 @@ @property (nonatomic, assign) CGPoint layoutPosition; @end + +NS_ASSUME_NONNULL_END From 309ecca444a2cfe34106b064ab9cb1ca5b5d9235 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Thu, 17 Sep 2015 11:42:38 -0700 Subject: [PATCH 09/60] In ASLayoutOptions, make initWithLayoutable: take a nullable argument --- AsyncDisplayKit/Layout/ASLayoutOptions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsyncDisplayKit/Layout/ASLayoutOptions.h b/AsyncDisplayKit/Layout/ASLayoutOptions.h index 799f3e6b..bda890cc 100644 --- a/AsyncDisplayKit/Layout/ASLayoutOptions.h +++ b/AsyncDisplayKit/Layout/ASLayoutOptions.h @@ -54,7 +54,7 @@ NS_ASSUME_NONNULL_BEGIN * * @return a new instance of ASLayoutOptions */ -- (instancetype)initWithLayoutable:(id)layoutable NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithLayoutable:(nullable id)layoutable NS_DESIGNATED_INITIALIZER; /** * Copies the values of layoutOptions into self. This is useful when placing a layoutable inside of another. Consider From c010ddad3bf8fe11baf52f44f08c4e6d62827ff0 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Thu, 17 Sep 2015 13:30:28 -0700 Subject: [PATCH 10/60] Update all the files in the Details group --- .../Details/ASAbstractLayoutController.h | 4 +++ .../Details/ASBasicImageDownloader.h | 3 ++ AsyncDisplayKit/Details/ASBatchContext.h | 4 +++ .../ASCollectionViewLayoutController.h | 4 +++ AsyncDisplayKit/Details/ASDataController.h | 28 +++++++++++-------- .../Details/ASDealloc2MainObject.h | 3 ++ .../Details/ASFlowLayoutController.h | 7 ++++- .../Details/ASHighlightOverlayLayer.h | 9 ++++-- AsyncDisplayKit/Details/ASImageProtocols.h | 19 +++++++------ AsyncDisplayKit/Details/ASIndexPath.h | 5 ++++ AsyncDisplayKit/Details/ASLayoutController.h | 17 +++++++---- .../ASMutableAttributedStringBuilder.h | 9 ++++-- AsyncDisplayKit/Details/ASRangeController.h | 13 +++++---- AsyncDisplayKit/Details/ASRangeHandler.h | 4 +++ .../Details/ASRangeHandlerPreload.h | 4 +++ .../Details/ASRangeHandlerRender.h | 4 +++ AsyncDisplayKit/Details/ASScrollDirection.h | 4 +++ .../Details/ASTextNodeCoreTextAdditions.h | 3 ++ AsyncDisplayKit/Details/ASTextNodeRenderer.h | 11 +++++--- AsyncDisplayKit/Details/ASTextNodeShadower.h | 3 ++ .../Details/ASTextNodeTextKitHelpers.h | 7 +++-- .../Details/ASTextNodeWordKerner.h | 3 ++ .../Details/CGRect+ASConvenience.h | 4 +++ ...MutableAttributedString+TextKitAdditions.h | 3 ++ .../UICollectionViewLayout+ASConvenience.h | 4 +++ .../Details/UIView+ASConvenience.h | 18 +++++++----- 26 files changed, 146 insertions(+), 51 deletions(-) diff --git a/AsyncDisplayKit/Details/ASAbstractLayoutController.h b/AsyncDisplayKit/Details/ASAbstractLayoutController.h index 45b92ece..f0cb3bb2 100644 --- a/AsyncDisplayKit/Details/ASAbstractLayoutController.h +++ b/AsyncDisplayKit/Details/ASAbstractLayoutController.h @@ -9,6 +9,8 @@ #import #import +NS_ASSUME_NONNULL_BEGIN + @interface ASAbstractLayoutController : NSObject - (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType; @@ -18,3 +20,5 @@ @property (nonatomic, assign) ASRangeTuningParameters tuningParameters ASDISPLAYNODE_DEPRECATED; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASBasicImageDownloader.h b/AsyncDisplayKit/Details/ASBasicImageDownloader.h index 2d962962..765a08e9 100644 --- a/AsyncDisplayKit/Details/ASBasicImageDownloader.h +++ b/AsyncDisplayKit/Details/ASBasicImageDownloader.h @@ -8,6 +8,7 @@ #import +NS_ASSUME_NONNULL_BEGIN /** * @abstract Simple NSURLSession-based image downloader. @@ -15,3 +16,5 @@ @interface ASBasicImageDownloader : NSObject @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASBatchContext.h b/AsyncDisplayKit/Details/ASBatchContext.h index 94c42293..452582f9 100644 --- a/AsyncDisplayKit/Details/ASBatchContext.h +++ b/AsyncDisplayKit/Details/ASBatchContext.h @@ -8,6 +8,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** * @abstract A context object to notify when batch fetches are finished or cancelled. */ @@ -58,3 +60,5 @@ - (void)beginBatchFetching; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASCollectionViewLayoutController.h b/AsyncDisplayKit/Details/ASCollectionViewLayoutController.h index 9aa25db0..632ba46b 100644 --- a/AsyncDisplayKit/Details/ASCollectionViewLayoutController.h +++ b/AsyncDisplayKit/Details/ASCollectionViewLayoutController.h @@ -9,6 +9,8 @@ #import #import +NS_ASSUME_NONNULL_BEGIN + @class ASCollectionView; @interface ASCollectionViewLayoutController : ASAbstractLayoutController @@ -16,3 +18,5 @@ - (instancetype)initWithCollectionView:(ASCollectionView *)collectionView; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASDataController.h b/AsyncDisplayKit/Details/ASDataController.h index 68e586da..6399f9a8 100644 --- a/AsyncDisplayKit/Details/ASDataController.h +++ b/AsyncDisplayKit/Details/ASDataController.h @@ -11,6 +11,8 @@ #import #import "ASFlowLayoutController.h" +NS_ASSUME_NONNULL_BEGIN + @class ASCellNode; @class ASDataController; @@ -66,22 +68,22 @@ typedef NSUInteger ASDataControllerAnimationOptions; Called for batch update. */ - (void)dataControllerBeginUpdates:(ASDataController *)dataController; -- (void)dataController:(ASDataController *)dataController endUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion; +- (void)dataController:(ASDataController *)dataController endUpdatesAnimated:(BOOL)animated completion:(void (^ _Nullable)(BOOL))completion; /** Called for insertion of elements. */ -- (void)dataController:(ASDataController *)dataController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; +- (void)dataController:(ASDataController *)dataController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; /** Called for deletion of elements. */ -- (void)dataController:(ASDataController *)dataController didDeleteNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; +- (void)dataController:(ASDataController *)dataController didDeleteNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; /** Called for insertion of sections. */ -- (void)dataController:(ASDataController *)dataController didInsertSections:(NSArray *)sections atIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; +- (void)dataController:(ASDataController *)dataController didInsertSections:(NSArray *> *)sections atIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; /** Called for deletion of sections. @@ -139,7 +141,7 @@ typedef NSUInteger ASDataControllerAnimationOptions; - (void)endUpdates; -- (void)endUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion; +- (void)endUpdatesAnimated:(BOOL)animated completion:(void (^ _Nullable)(BOOL))completion; - (void)insertSections:(NSIndexSet *)sections withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; @@ -149,11 +151,11 @@ typedef NSUInteger ASDataControllerAnimationOptions; - (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; -- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; +- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; -- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; +- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; -- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; +- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; /** * Re-measures all loaded nodes. Used to respond to a change in size of the containing view @@ -163,7 +165,7 @@ typedef NSUInteger ASDataControllerAnimationOptions; - (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; -- (void)reloadDataWithAnimationOptions:(ASDataControllerAnimationOptions)animationOptions completion:(void (^)())completion; +- (void)reloadDataWithAnimationOptions:(ASDataControllerAnimationOptions)animationOptions completion:(void (^ _Nullable)())completion; /** @name Data Querying */ @@ -171,10 +173,12 @@ typedef NSUInteger ASDataControllerAnimationOptions; - (NSUInteger)numberOfRowsInSection:(NSUInteger)section; -- (ASCellNode *)nodeAtIndexPath:(NSIndexPath *)indexPath; +- (nullable ASCellNode *)nodeAtIndexPath:(NSIndexPath *)indexPath; -- (NSArray *)nodesAtIndexPaths:(NSArray *)indexPaths; +- (NSArray *)nodesAtIndexPaths:(NSArray *)indexPaths; -- (NSArray *)completedNodes; // This provides efficient access to the entire _completedNodes multidimensional array. +- (NSArray *> *)completedNodes; // This provides efficient access to the entire _completedNodes multidimensional array. @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASDealloc2MainObject.h b/AsyncDisplayKit/Details/ASDealloc2MainObject.h index 06c298a5..88c08ba9 100644 --- a/AsyncDisplayKit/Details/ASDealloc2MainObject.h +++ b/AsyncDisplayKit/Details/ASDealloc2MainObject.h @@ -8,6 +8,7 @@ #import +NS_ASSUME_NONNULL_BEGIN /** * _OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN permits classes to implement their own reference counting and enforce @@ -19,3 +20,5 @@ - (BOOL)_isDeallocating; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASFlowLayoutController.h b/AsyncDisplayKit/Details/ASFlowLayoutController.h index 9b61a37b..a0845ed2 100644 --- a/AsyncDisplayKit/Details/ASFlowLayoutController.h +++ b/AsyncDisplayKit/Details/ASFlowLayoutController.h @@ -9,6 +9,9 @@ #import #import +NS_ASSUME_NONNULL_BEGIN + +@class ASCellNode; typedef NS_ENUM(NSUInteger, ASFlowLayoutDirection) { ASFlowLayoutDirectionVertical, @@ -17,7 +20,7 @@ typedef NS_ENUM(NSUInteger, ASFlowLayoutDirection) { @protocol ASFlowLayoutControllerDataSource -- (NSArray *)completedNodes; // This provides access to ASDataController's _completedNodes multidimensional array. +- (NSArray *> *)completedNodes; // This provides access to ASDataController's _completedNodes multidimensional array. @end @@ -33,3 +36,5 @@ typedef NS_ENUM(NSUInteger, ASFlowLayoutDirection) { - (instancetype)initWithScrollOption:(ASFlowLayoutDirection)layoutDirection; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASHighlightOverlayLayer.h b/AsyncDisplayKit/Details/ASHighlightOverlayLayer.h index 6b7c236f..736ff087 100644 --- a/AsyncDisplayKit/Details/ASHighlightOverlayLayer.h +++ b/AsyncDisplayKit/Details/ASHighlightOverlayLayer.h @@ -8,6 +8,7 @@ #import +NS_ASSUME_NONNULL_BEGIN @interface ASHighlightOverlayLayer : CALayer @@ -19,16 +20,16 @@ @param rects Array containing CGRects wrapped in NSValue. @param targetLayer The layer that the rects are relative to. The rects will be translated to the receiver's coordinate space when rendering. */ -- (id)initWithRects:(NSArray *)rects targetLayer:(id)targetLayer; +- (id)initWithRects:(NSArray *)rects targetLayer:(nullable CALayer *)targetLayer; /** @summary Initializes with CGRects for the highlighting, in the receiver's coordinate space. @param rects Array containing CGRects wrapped in NSValue. */ -- (id)initWithRects:(NSArray *)rects; +- (id)initWithRects:(NSArray *)rects; -@property (atomic, strong) __attribute__((NSObject)) CGColorRef highlightColor; +@property (nullable, atomic, strong) __attribute__((NSObject)) CGColorRef highlightColor; @property (atomic, weak) CALayer *targetLayer; @end @@ -42,3 +43,5 @@ @property (nonatomic, assign, setter=as_setAllowsHighlightDrawing:) BOOL as_allowsHighlightDrawing; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASImageProtocols.h b/AsyncDisplayKit/Details/ASImageProtocols.h index 38465a2d..f0720d51 100644 --- a/AsyncDisplayKit/Details/ASImageProtocols.h +++ b/AsyncDisplayKit/Details/ASImageProtocols.h @@ -9,6 +9,7 @@ #import #import +NS_ASSUME_NONNULL_BEGIN @protocol ASImageCacheProtocol @@ -23,9 +24,9 @@ @discussion If `URL` is nil, `completion` will be invoked immediately with a nil image. This method should not block the calling thread as it is likely to be called from the main thread. */ -- (void)fetchCachedImageWithURL:(NSURL *)URL - callbackQueue:(dispatch_queue_t)callbackQueue - completion:(void (^)(CGImageRef imageFromCache))completion; +- (void)fetchCachedImageWithURL:(nullable NSURL *)URL + callbackQueue:(nullable dispatch_queue_t)callbackQueue + completion:(void (^)(CGImageRef _Nullable imageFromCache))completion; @end @@ -48,10 +49,10 @@ @result An opaque identifier to be used in canceling the download, via `cancelImageDownloadForIdentifier:`. You must retain the identifier if you wish to use it later. */ -- (id)downloadImageWithURL:(NSURL *)URL - callbackQueue:(dispatch_queue_t)callbackQueue - downloadProgressBlock:(void (^)(CGFloat progress))downloadProgressBlock - completion:(void (^)(CGImageRef image, NSError *error))completion; +- (id)downloadImageWithURL:(nullable NSURL *)URL + callbackQueue:(nullable dispatch_queue_t)callbackQueue + downloadProgressBlock:(void (^ _Nullable)(CGFloat progress))downloadProgressBlock + completion:(void (^ _Nullable)(CGImageRef image, NSError *error))completion; /** @abstract Cancels an image download. @@ -59,6 +60,8 @@ `downloadImageWithURL:callbackQueue:downloadProgressBlock:completion:`. @discussion This method has no effect if `downloadIdentifier` is nil. */ -- (void)cancelImageDownloadForIdentifier:(id)downloadIdentifier; +- (void)cancelImageDownloadForIdentifier:(nullable id)downloadIdentifier; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASIndexPath.h b/AsyncDisplayKit/Details/ASIndexPath.h index a6eb514a..fde2b240 100644 --- a/AsyncDisplayKit/Details/ASIndexPath.h +++ b/AsyncDisplayKit/Details/ASIndexPath.h @@ -19,8 +19,11 @@ typedef struct { ASIndexPath end; } ASIndexPathRange; +NS_ASSUME_NONNULL_BEGIN + ASDISPLAYNODE_EXTERN_C_BEGIN + extern ASIndexPath ASIndexPathMake(NSInteger section, NSInteger row); extern BOOL ASIndexPathEqualToIndexPath(ASIndexPath first, ASIndexPath second); @@ -41,3 +44,5 @@ ASDISPLAYNODE_EXTERN_C_END - (ASIndexPath)ASIndexPathValue; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASLayoutController.h b/AsyncDisplayKit/Details/ASLayoutController.h index b45efd87..70f6bd80 100644 --- a/AsyncDisplayKit/Details/ASLayoutController.h +++ b/AsyncDisplayKit/Details/ASLayoutController.h @@ -12,6 +12,9 @@ #import #import +NS_ASSUME_NONNULL_BEGIN + +@class ASCellNode; typedef struct { CGFloat leadingBufferScreenfuls; @@ -27,26 +30,28 @@ typedef struct { */ - (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType; -- (BOOL)shouldUpdateForVisibleIndexPaths:(NSArray *)indexPaths viewportSize:(CGSize)viewportSize rangeType:(ASLayoutRangeType)rangeType; +- (BOOL)shouldUpdateForVisibleIndexPaths:(NSArray *)indexPaths viewportSize:(CGSize)viewportSize rangeType:(ASLayoutRangeType)rangeType; - (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection viewportSize:(CGSize)viewportSize rangeType:(ASLayoutRangeType)rangeType; @property (nonatomic, assign) ASRangeTuningParameters tuningParameters ASDISPLAYNODE_DEPRECATED; -- (BOOL)shouldUpdateForVisibleIndexPath:(NSArray *)indexPath viewportSize:(CGSize)viewportSize ASDISPLAYNODE_DEPRECATED; +- (BOOL)shouldUpdateForVisibleIndexPath:(NSIndexPath *)indexPath viewportSize:(CGSize)viewportSize ASDISPLAYNODE_DEPRECATED; - (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection viewportSize:(CGSize)viewportSize ASDISPLAYNODE_DEPRECATED; @optional -- (void)insertNodesAtIndexPaths:(NSArray *)indexPaths withSizes:(NSArray *)nodeSizes; +- (void)insertNodesAtIndexPaths:(NSArray *)indexPaths withSizes:(NSArray *)nodeSizes; -- (void)deleteNodesAtIndexPaths:(NSArray *)indexPaths; +- (void)deleteNodesAtIndexPaths:(NSArray *)indexPaths; -- (void)insertSections:(NSArray *)sections atIndexSet:(NSIndexSet *)indexSet; +- (void)insertSections:(NSArray*> *)sections atIndexSet:(NSIndexSet *)indexSet; - (void)deleteSectionsAtIndexSet:(NSIndexSet *)indexSet; -- (void)setVisibleNodeIndexPaths:(NSArray *)indexPaths; +- (void)setVisibleNodeIndexPaths:(NSArray *)indexPaths; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASMutableAttributedStringBuilder.h b/AsyncDisplayKit/Details/ASMutableAttributedStringBuilder.h index 99d7c9ad..4df67ada 100644 --- a/AsyncDisplayKit/Details/ASMutableAttributedStringBuilder.h +++ b/AsyncDisplayKit/Details/ASMutableAttributedStringBuilder.h @@ -8,6 +8,7 @@ #import +NS_ASSUME_NONNULL_BEGIN /* * Use this class to compose new attributed strings. You may use the normal @@ -38,14 +39,14 @@ */ @interface ASMutableAttributedStringBuilder : NSMutableAttributedString -- (instancetype)initWithString:(NSString *)str attributes:(NSDictionary *)attrs; +- (instancetype)initWithString:(NSString *)str attributes:(nullable NSDictionary *)attrs; - (instancetype)initWithAttributedString:(NSAttributedString *)attrStr; - (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str; -- (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range; +- (void)setAttributes:(nullable NSDictionary *)attrs range:(NSRange)range; - (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)range; -- (void)addAttributes:(NSDictionary *)attrs range:(NSRange)range; +- (void)addAttributes:(NSDictionary *)attrs range:(NSRange)range; - (void)removeAttribute:(NSString *)name range:(NSRange)range; - (void)replaceCharactersInRange:(NSRange)range withAttributedString:(NSAttributedString *)attrString; @@ -57,3 +58,5 @@ - (NSMutableAttributedString *)composedAttributedString; @end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/AsyncDisplayKit/Details/ASRangeController.h b/AsyncDisplayKit/Details/ASRangeController.h index 9d5bbe57..aaf67689 100644 --- a/AsyncDisplayKit/Details/ASRangeController.h +++ b/AsyncDisplayKit/Details/ASRangeController.h @@ -13,6 +13,7 @@ #import #import +NS_ASSUME_NONNULL_BEGIN @protocol ASRangeControllerDelegate; @@ -65,7 +66,7 @@ * * @returns an array of index paths corresponding to the nodes currently visible onscreen (i.e., the visible range). */ -- (NSArray *)rangeControllerVisibleNodeIndexPaths:(ASRangeController *)rangeController; +- (NSArray *)rangeControllerVisibleNodeIndexPaths:(ASRangeController *)rangeController; /** * @param rangeController Sender. @@ -88,7 +89,7 @@ * @param animated NO if all animations are disabled. YES otherwise. * @param completion Completion block. */ -- (void)rangeController:(ASRangeController * )rangeController endUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion; +- (void)rangeController:(ASRangeController * )rangeController endUpdatesAnimated:(BOOL)animated completion:(void (^ _Nullable)(BOOL))completion; /** * Fetch nodes at specific index paths. @@ -97,7 +98,7 @@ * * @param indexPaths Index paths. */ -- (NSArray *)rangeController:(ASRangeController *)rangeController nodesAtIndexPaths:(NSArray *)indexPaths; +- (NSArray *)rangeController:(ASRangeController *)rangeController nodesAtIndexPaths:(NSArray *)indexPaths; /** * Called for nodes insertion. @@ -110,7 +111,7 @@ * * @param animationOptions Animation options. See ASDataControllerAnimationOptions. */ -- (void)rangeController:(ASRangeController *)rangeController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; +- (void)rangeController:(ASRangeController *)rangeController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; /** * Called for nodes deletion. @@ -123,7 +124,7 @@ * * @param animationOptions Animation options. See ASDataControllerAnimationOptions. */ -- (void)rangeController:(ASRangeController *)rangeController didDeleteNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; +- (void)rangeController:(ASRangeController *)rangeController didDeleteNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; /** * Called for section insertion. @@ -148,3 +149,5 @@ - (void)rangeController:(ASRangeController *)rangeController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; @end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/AsyncDisplayKit/Details/ASRangeHandler.h b/AsyncDisplayKit/Details/ASRangeHandler.h index 22a7c564..136736f4 100644 --- a/AsyncDisplayKit/Details/ASRangeHandler.h +++ b/AsyncDisplayKit/Details/ASRangeHandler.h @@ -10,6 +10,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + @class ASDisplayNode; @protocol ASRangeHandler @@ -20,3 +22,5 @@ - (void)node:(ASDisplayNode *)node exitedRangeOfType:(ASLayoutRangeType)rangeType; @end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/AsyncDisplayKit/Details/ASRangeHandlerPreload.h b/AsyncDisplayKit/Details/ASRangeHandlerPreload.h index 7dc01138..eb7c34f9 100644 --- a/AsyncDisplayKit/Details/ASRangeHandlerPreload.h +++ b/AsyncDisplayKit/Details/ASRangeHandlerPreload.h @@ -10,6 +10,10 @@ #import +NS_ASSUME_NONNULL_BEGIN + @interface ASRangeHandlerPreload : NSObject @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASRangeHandlerRender.h b/AsyncDisplayKit/Details/ASRangeHandlerRender.h index b064cb6a..8b00982b 100644 --- a/AsyncDisplayKit/Details/ASRangeHandlerRender.h +++ b/AsyncDisplayKit/Details/ASRangeHandlerRender.h @@ -10,6 +10,10 @@ #import +NS_ASSUME_NONNULL_BEGIN + @interface ASRangeHandlerRender : NSObject @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASScrollDirection.h b/AsyncDisplayKit/Details/ASScrollDirection.h index a46295cf..2d75703d 100644 --- a/AsyncDisplayKit/Details/ASScrollDirection.h +++ b/AsyncDisplayKit/Details/ASScrollDirection.h @@ -10,6 +10,8 @@ #import "ASBaseDefines.h" +NS_ASSUME_NONNULL_BEGIN + typedef NS_OPTIONS(NSInteger, ASScrollDirection) { ASScrollDirectionNone = 0, ASScrollDirectionRight = 1 << 0, @@ -32,3 +34,5 @@ BOOL ASScrollDirectionContainsUp(ASScrollDirection scrollDirection); BOOL ASScrollDirectionContainsDown(ASScrollDirection scrollDirection); ASDISPLAYNODE_EXTERN_C_END + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASTextNodeCoreTextAdditions.h b/AsyncDisplayKit/Details/ASTextNodeCoreTextAdditions.h index ce74957e..d16aa902 100644 --- a/AsyncDisplayKit/Details/ASTextNodeCoreTextAdditions.h +++ b/AsyncDisplayKit/Details/ASTextNodeCoreTextAdditions.h @@ -11,6 +11,7 @@ #import +NS_ASSUME_NONNULL_BEGIN ASDISPLAYNODE_EXTERN_C_BEGIN /** @@ -81,3 +82,5 @@ ASDISPLAYNODE_EXTERN_C_END + (instancetype)paragraphStyleWithCTParagraphStyle:(CTParagraphStyleRef)coreTextParagraphStyle; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASTextNodeRenderer.h b/AsyncDisplayKit/Details/ASTextNodeRenderer.h index 3b80bb16..dd5804e2 100644 --- a/AsyncDisplayKit/Details/ASTextNodeRenderer.h +++ b/AsyncDisplayKit/Details/ASTextNodeRenderer.h @@ -8,6 +8,7 @@ #import +NS_ASSUME_NONNULL_BEGIN typedef void (^as_renderer_index_block_t)(NSUInteger characterIndex, CGRect glyphBoundingRect, @@ -46,10 +47,10 @@ typedef NS_ENUM(NSUInteger, ASTextNodeRendererMeasureOption) { @interface ASTextNodeRenderer : NSObject - (instancetype)initWithAttributedString:(NSAttributedString *)attributedString - truncationString:(NSAttributedString *)truncationString + truncationString:(nullable NSAttributedString *)truncationString truncationMode:(NSLineBreakMode)truncationMode maximumLineCount:(NSUInteger)maximumLineCount - exclusionPaths:(NSArray *)exclusionPaths + exclusionPaths:(nullable NSArray *)exclusionPaths constrainedSize:(CGSize)constrainedSize; /* * Designated Initializer @@ -59,7 +60,7 @@ typedef NS_ENUM(NSUInteger, ASTextNodeRendererMeasureOption) { * so feel free */ - (instancetype)initWithAttributedString:(NSAttributedString *)attributedString - truncationString:(NSAttributedString *)truncationString + truncationString:(nullable NSAttributedString *)truncationString truncationMode:(NSLineBreakMode)truncationMode maximumLineCount:(NSUInteger)maximumLineCount constrainedSize:(CGSize)constrainedSize; @@ -129,7 +130,7 @@ typedef NS_ENUM(NSUInteger, ASTextNodeRendererMeasureOption) { * * Triggers initialization of textkit components, truncation, and sizing. */ -- (NSArray *)rectsForTextRange:(NSRange)textRange +- (NSArray *)rectsForTextRange:(NSRange)textRange measureOption:(ASTextNodeRendererMeasureOption)measureOption; /* @@ -186,3 +187,5 @@ typedef NS_ENUM(NSUInteger, ASTextNodeRendererMeasureOption) { - (NSUInteger)lineCount; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASTextNodeShadower.h b/AsyncDisplayKit/Details/ASTextNodeShadower.h index 59744897..3b0adca3 100644 --- a/AsyncDisplayKit/Details/ASTextNodeShadower.h +++ b/AsyncDisplayKit/Details/ASTextNodeShadower.h @@ -9,6 +9,7 @@ #import #import +NS_ASSUME_NONNULL_BEGIN /** * @abstract Negates/inverts a UIEdgeInsets. @@ -67,3 +68,5 @@ static inline UIEdgeInsets ASDNEdgeInsetsInvert(UIEdgeInsets insets) - (void)setShadowInContext:(CGContextRef)context; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASTextNodeTextKitHelpers.h b/AsyncDisplayKit/Details/ASTextNodeTextKitHelpers.h index 22fc9efb..d51dab0f 100644 --- a/AsyncDisplayKit/Details/ASTextNodeTextKitHelpers.h +++ b/AsyncDisplayKit/Details/ASTextNodeTextKitHelpers.h @@ -11,6 +11,7 @@ #import #import +NS_ASSUME_NONNULL_BEGIN @interface ASTextKitComponents : NSObject @@ -21,7 +22,7 @@ @return An `ASTextKitComponents` containing the created components. The text view component will be nil. @discussion The returned components will be hooked up together, so they are ready for use as a system upon return. */ -+ (ASTextKitComponents *)componentsWithAttributedSeedString:(NSAttributedString *)attributedSeedString ++ (ASTextKitComponents *)componentsWithAttributedSeedString:(nullable NSAttributedString *)attributedSeedString textContainerSize:(CGSize)textContainerSize; /** @@ -35,6 +36,8 @@ @property (nonatomic, strong, readonly) NSTextStorage *textStorage; @property (nonatomic, strong, readonly) NSTextContainer *textContainer; @property (nonatomic, strong, readonly) NSLayoutManager *layoutManager; -@property (nonatomic, strong) UITextView *textView; +@property (nullable, nonatomic, strong) UITextView *textView; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASTextNodeWordKerner.h b/AsyncDisplayKit/Details/ASTextNodeWordKerner.h index 1be6390c..a98654cf 100644 --- a/AsyncDisplayKit/Details/ASTextNodeWordKerner.h +++ b/AsyncDisplayKit/Details/ASTextNodeWordKerner.h @@ -9,6 +9,7 @@ #import #import +NS_ASSUME_NONNULL_BEGIN /** @abstract This class acts as the NSLayoutManagerDelegate for ASTextNode. @@ -28,3 +29,5 @@ */ @end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/AsyncDisplayKit/Details/CGRect+ASConvenience.h b/AsyncDisplayKit/Details/CGRect+ASConvenience.h index a9cc714a..9743eb49 100644 --- a/AsyncDisplayKit/Details/CGRect+ASConvenience.h +++ b/AsyncDisplayKit/Details/CGRect+ASConvenience.h @@ -10,9 +10,13 @@ #import "ASBaseDefines.h" +NS_ASSUME_NONNULL_BEGIN + ASDISPLAYNODE_EXTERN_C_BEGIN CGRect asdk_CGRectExpandHorizontally(CGRect rect, CGFloat negativeMultiplier, CGFloat positiveMultiplier); CGRect asdk_CGRectExpandVertically(CGRect rect, CGFloat negativeMultiplier, CGFloat positiveMultiplier); ASDISPLAYNODE_EXTERN_C_END + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/NSMutableAttributedString+TextKitAdditions.h b/AsyncDisplayKit/Details/NSMutableAttributedString+TextKitAdditions.h index 8810ba35..cd2dd1eb 100644 --- a/AsyncDisplayKit/Details/NSMutableAttributedString+TextKitAdditions.h +++ b/AsyncDisplayKit/Details/NSMutableAttributedString+TextKitAdditions.h @@ -8,6 +8,7 @@ #import +NS_ASSUME_NONNULL_BEGIN @interface NSMutableAttributedString (TextKitAdditions) @@ -20,3 +21,5 @@ - (void)attributeTextInRange:(NSRange)range withTextKitParagraphStyle:(NSParagraphStyle *)paragraphStyle; @end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/AsyncDisplayKit/Details/UICollectionViewLayout+ASConvenience.h b/AsyncDisplayKit/Details/UICollectionViewLayout+ASConvenience.h index 1853be6f..4710cbdf 100644 --- a/AsyncDisplayKit/Details/UICollectionViewLayout+ASConvenience.h +++ b/AsyncDisplayKit/Details/UICollectionViewLayout+ASConvenience.h @@ -8,8 +8,12 @@ #import +NS_ASSUME_NONNULL_BEGIN + @interface UICollectionViewLayout (ASConvenience) - (BOOL)asdk_isFlowLayout; @end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/AsyncDisplayKit/Details/UIView+ASConvenience.h b/AsyncDisplayKit/Details/UIView+ASConvenience.h index d1f00324..dfd59167 100644 --- a/AsyncDisplayKit/Details/UIView+ASConvenience.h +++ b/AsyncDisplayKit/Details/UIView+ASConvenience.h @@ -8,6 +8,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** These are the properties we support from CALayer (implemented in the pending state) @@ -18,7 +20,7 @@ @property (nonatomic, assign) CGPoint position; @property (nonatomic, assign) CGFloat zPosition; @property (nonatomic, assign) CGPoint anchorPoint; -@property (nonatomic, retain) id contents; +@property (nullable, nonatomic, retain) id contents; @property (nonatomic, assign) CGFloat cornerRadius; @property (nonatomic, assign) CGFloat contentsScale; @property (nonatomic, assign) CATransform3D transform; @@ -30,9 +32,9 @@ @property (nonatomic, assign) CGFloat shadowRadius; @property (nonatomic, assign) CGFloat borderWidth; @property (nonatomic, assign, getter = isOpaque) BOOL opaque; -@property (nonatomic, retain) __attribute__((NSObject)) CGColorRef borderColor; -@property (nonatomic, copy) NSString *asyncdisplaykit_name; -@property (nonatomic, retain) __attribute__((NSObject)) CGColorRef backgroundColor; +@property (nullable, nonatomic, retain) __attribute__((NSObject)) CGColorRef borderColor; +@property (nullable, nonatomic, copy) NSString *asyncdisplaykit_name; +@property (nullable, nonatomic, retain) __attribute__((NSObject)) CGColorRef backgroundColor; @property (nonatomic, assign) BOOL allowsEdgeAntialiasing; @property (nonatomic, assign) unsigned int edgeAntialiasingMask; @@ -50,7 +52,7 @@ @property (nonatomic, getter=isHidden) BOOL hidden; @property (nonatomic, assign) BOOL autoresizesSubviews; @property (nonatomic, assign) UIViewAutoresizing autoresizingMask; -@property (nonatomic, retain) UIColor *tintColor; +@property (nonatomic, retain, null_resettable) UIColor *tintColor; @property (nonatomic, assign) CGFloat alpha; @property (nonatomic, assign) CGRect bounds; @property (nonatomic, assign) UIViewContentMode contentMode; @@ -76,10 +78,12 @@ */ // Accessibility identification support -@property (nonatomic, copy) NSString *accessibilityIdentifier; +@property (nullable, nonatomic, copy) NSString *accessibilityIdentifier; @end @interface CALayer (ASDisplayNodeLayer) -@property (atomic, copy) NSString *asyncdisplaykit_name; +@property (nullable, atomic, copy) NSString *asyncdisplaykit_name; @end + +NS_ASSUME_NONNULL_END From 38706d0962a84a16c28badc5bcbf33245c9e434d Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Thu, 17 Sep 2015 14:22:29 -0700 Subject: [PATCH 11/60] Fix nullability in ASImageDownloaderProtocol completion handler --- AsyncDisplayKit/Details/ASImageProtocols.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsyncDisplayKit/Details/ASImageProtocols.h b/AsyncDisplayKit/Details/ASImageProtocols.h index f0720d51..2235dafe 100644 --- a/AsyncDisplayKit/Details/ASImageProtocols.h +++ b/AsyncDisplayKit/Details/ASImageProtocols.h @@ -52,7 +52,7 @@ NS_ASSUME_NONNULL_BEGIN - (id)downloadImageWithURL:(nullable NSURL *)URL callbackQueue:(nullable dispatch_queue_t)callbackQueue downloadProgressBlock:(void (^ _Nullable)(CGFloat progress))downloadProgressBlock - completion:(void (^ _Nullable)(CGImageRef image, NSError *error))completion; + completion:(void (^ _Nullable)(CGImageRef _Nullable image, NSError * _Nullable error))completion; /** @abstract Cancels an image download. From ba9a742999f5d5baeae5df0768bd738c233cc588 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Thu, 17 Sep 2015 14:48:42 -0700 Subject: [PATCH 12/60] Fix nullability of ASImageDownloaderProtocol to conform to ASBasicImageDownloader behavior --- AsyncDisplayKit/Details/ASImageProtocols.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/AsyncDisplayKit/Details/ASImageProtocols.h b/AsyncDisplayKit/Details/ASImageProtocols.h index 2235dafe..8a235083 100644 --- a/AsyncDisplayKit/Details/ASImageProtocols.h +++ b/AsyncDisplayKit/Details/ASImageProtocols.h @@ -43,13 +43,11 @@ NS_ASSUME_NONNULL_BEGIN @param completion The block to be invoked when the download has completed, or has failed. @param image The image that was downloaded, if the image could be successfully downloaded; nil otherwise. @param error An error describing why the download of `URL` failed, if the download failed; nil otherwise. - @discussion If `URL` is nil, `completion` will be invoked immediately with a nil image and an error describing why the - download failed. This method is likely to be called on the main thread, so any custom implementations should make - sure to background any expensive download operations. + @discussion This method is likely to be called on the main thread, so any custom implementations should make sure to background any expensive download operations. @result An opaque identifier to be used in canceling the download, via `cancelImageDownloadForIdentifier:`. You must retain the identifier if you wish to use it later. */ -- (id)downloadImageWithURL:(nullable NSURL *)URL +- (id)downloadImageWithURL:(NSURL *)URL callbackQueue:(nullable dispatch_queue_t)callbackQueue downloadProgressBlock:(void (^ _Nullable)(CGFloat progress))downloadProgressBlock completion:(void (^ _Nullable)(CGImageRef _Nullable image, NSError * _Nullable error))completion; From fd3a90a3ed40a8d49d41bc83cb214d548bf62c5c Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Thu, 17 Sep 2015 14:56:39 -0700 Subject: [PATCH 13/60] Make image download token optional --- AsyncDisplayKit/Details/ASImageProtocols.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsyncDisplayKit/Details/ASImageProtocols.h b/AsyncDisplayKit/Details/ASImageProtocols.h index 8a235083..ba04eaaa 100644 --- a/AsyncDisplayKit/Details/ASImageProtocols.h +++ b/AsyncDisplayKit/Details/ASImageProtocols.h @@ -47,7 +47,7 @@ NS_ASSUME_NONNULL_BEGIN @result An opaque identifier to be used in canceling the download, via `cancelImageDownloadForIdentifier:`. You must retain the identifier if you wish to use it later. */ -- (id)downloadImageWithURL:(NSURL *)URL +- (nullable id)downloadImageWithURL:(NSURL *)URL callbackQueue:(nullable dispatch_queue_t)callbackQueue downloadProgressBlock:(void (^ _Nullable)(CGFloat progress))downloadProgressBlock completion:(void (^ _Nullable)(CGImageRef _Nullable image, NSError * _Nullable error))completion; From f20a0d4bc0ffdc906340b4128b5a807e1c1e2a5c Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Thu, 17 Sep 2015 19:56:21 -0700 Subject: [PATCH 14/60] Add some nullables in ASTextNode --- AsyncDisplayKit/ASTextNode.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AsyncDisplayKit/ASTextNode.h b/AsyncDisplayKit/ASTextNode.h index e7fdf85f..72b28cf2 100644 --- a/AsyncDisplayKit/ASTextNode.h +++ b/AsyncDisplayKit/ASTextNode.h @@ -46,14 +46,14 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) { @abstract The attributedString to use when the text must be truncated. @discussion Defaults to a localized ellipsis character. */ -@property (nonatomic, copy) NSAttributedString *truncationAttributedString; +@property (nullable, nonatomic, copy) NSAttributedString *truncationAttributedString; /** @summary The second attributed string appended for truncation. @discussion This string will be highlighted on touches. @default nil */ -@property (nonatomic, copy) NSAttributedString *additionalTruncationMessage; +@property (nullable, nonatomic, copy) NSAttributedString *additionalTruncationMessage; /** @abstract Determines how the text is truncated to fit within the receiver's maximum size. @@ -77,7 +77,7 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) { */ @property (nonatomic, readonly, assign) NSUInteger lineCount; -@property (nonatomic, strong) NSArray *exclusionPaths; +@property (nullable, nonatomic, strong) NSArray *exclusionPaths; #pragma mark - Placeholders From f37a88d2e40b9e783494aedc1677fa639d9ed62c Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Fri, 18 Sep 2015 23:32:52 -0700 Subject: [PATCH 15/60] Give a prefix to make ASImageIdentifier typealias --- AsyncDisplayKit/ASMultiplexImageNode.h | 27 +++++++++++++------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/AsyncDisplayKit/ASMultiplexImageNode.h b/AsyncDisplayKit/ASMultiplexImageNode.h index 027d9b3d..d395d962 100644 --- a/AsyncDisplayKit/ASMultiplexImageNode.h +++ b/AsyncDisplayKit/ASMultiplexImageNode.h @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN @protocol ASMultiplexImageNodeDelegate; @protocol ASMultiplexImageNodeDataSource; -typedef __kindof NSObject * ImageIdentifier; +typedef __kindof NSObject * ASImageIdentifier; extern NSString *const ASMultiplexImageNodeErrorDomain; @@ -38,8 +38,7 @@ typedef NS_ENUM(NSUInteger, ASMultiplexImageNodeErrorCode) { * @abstract ASMultiplexImageNode is an image node that can load and display multiple versions of an image. For * example, it can display a low-resolution version of an image while the high-resolution version is loading. * - * @discussion ASMultiplexImageNode begins loading images when its property is set. For each image - * identifier, the data source can either return a UIImage directly, or a URL the image node should load. + * @discussion ASMultiplexImageNode begins loading images when its for more information on the image loading process. */ -@property (nonatomic, readwrite, copy) NSArray *imageIdentifiers; +@property (nonatomic, readwrite, copy) NSArray *imageIdentifiers; /** - * @abstract Notify the receiver that its data source has new UIImages or NSURLs available for . + * @abstract Notify the receiver SSAAthat its data source has new UIImages or NSURLs available for . * * @discussion If a higher-quality image than is currently displayed is now available, it will be loaded. */ @@ -94,12 +93,12 @@ typedef NS_ENUM(NSUInteger, ASMultiplexImageNodeErrorCode) { * * @discussion This value may differ from if the image hasn't yet been displayed. */ -@property (nullable, nonatomic, readonly) ImageIdentifier loadedImageIdentifier; +@property (nullable, nonatomic, readonly) ASImageIdentifier loadedImageIdentifier; /** * @abstract The identifier for the image that the receiver is currently displaying, or nil. */ -@property (nullable, nonatomic, readonly) ImageIdentifier displayedImageIdentifier; +@property (nullable, nonatomic, readonly) ASImageIdentifier displayedImageIdentifier; @end @@ -127,7 +126,7 @@ typedef NS_ENUM(NSUInteger, ASMultiplexImageNodeErrorCode) { */ - (void)multiplexImageNode:(ASMultiplexImageNode *)imageNode didUpdateDownloadProgress:(CGFloat)downloadProgress - forImageWithIdentifier:(ImageIdentifier)imageIdentifier; + forImageWithIdentifier:(ASImageIdentifier)imageIdentifier; /** * @abstract Notification that the image node's download has finished. @@ -136,7 +135,7 @@ typedef NS_ENUM(NSUInteger, ASMultiplexImageNodeErrorCode) { * @param error The error that occurred while downloading, if one occurred; nil otherwise. */ - (void)multiplexImageNode:(ASMultiplexImageNode *)imageNode -didFinishDownloadingImageWithIdentifier:(ImageIdentifier)imageIdentifier +didFinishDownloadingImageWithIdentifier:(ASImageIdentifier)imageIdentifier error:(nullable NSError *)error; /** @@ -151,9 +150,9 @@ didFinishDownloadingImageWithIdentifier:(ImageIdentifier)imageIdentifier */ - (void)multiplexImageNode:(ASMultiplexImageNode *)imageNode didUpdateImage:(nullable UIImage *)image - withIdentifier:(nullable ImageIdentifier)imageIdentifier + withIdentifier:(nullable ASImageIdentifier)imageIdentifier fromImage:(nullable UIImage *)previousImage - withIdentifier:(nullable ImageIdentifier)previousImageIdentifier; + withIdentifier:(nullable ASImageIdentifier)previousImageIdentifier; /** * @abstract Notification that the image node displayed a new image. @@ -164,7 +163,7 @@ didFinishDownloadingImageWithIdentifier:(ImageIdentifier)imageIdentifier */ - (void)multiplexImageNode:(ASMultiplexImageNode *)imageNode didDisplayUpdatedImage:(nullable UIImage *)image - withIdentifier:(nullable ImageIdentifier)imageIdentifier; + withIdentifier:(nullable ASImageIdentifier)imageIdentifier; /** * @abstract Notification that the image node finished displaying an image. @@ -192,7 +191,7 @@ didFinishDownloadingImageWithIdentifier:(ImageIdentifier)imageIdentifier * URL to the image via -multiplexImageNode:URLForImageIdentifier:. * @returns A UIImage corresponding to `imageIdentifier`, or nil if none is available. */ -- (nullable UIImage *)multiplexImageNode:(ASMultiplexImageNode *)imageNode imageForImageIdentifier:(ImageIdentifier)imageIdentifier; +- (nullable UIImage *)multiplexImageNode:(ASMultiplexImageNode *)imageNode imageForImageIdentifier:(ASImageIdentifier)imageIdentifier; /** * @abstract An image URL for the specified identifier. @@ -203,7 +202,7 @@ didFinishDownloadingImageWithIdentifier:(ImageIdentifier)imageIdentifier * multiplexImageNode:imageForImageIdentifier:]> instead. * @returns An NSURL for the image identified by `imageIdentifier`, or nil if none is available. */ -- (nullable NSURL *)multiplexImageNode:(ASMultiplexImageNode *)imageNode URLForImageIdentifier:(ImageIdentifier)imageIdentifier; +- (nullable NSURL *)multiplexImageNode:(ASMultiplexImageNode *)imageNode URLForImageIdentifier:(ASImageIdentifier)imageIdentifier; @end From ffbf84f13b54a44dbd0b7ef64e3450901648794d Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Sat, 19 Sep 2015 11:05:01 -0700 Subject: [PATCH 16/60] Point travis at 9.0 SDK --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 4d09065e..60531d5a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ language: objective-c osx_image: xcode7 +xcode_sdk: + - iphonesimulator9.0 before_install: - brew update - brew reinstall xctool From dc5650d6fa62a6378471b862c439a0ef0f9a2f0d Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Sat, 19 Sep 2015 11:14:22 -0700 Subject: [PATCH 17/60] Revert "Point travis at 9.0 SDK" This reverts commit ffbf84f13b54a44dbd0b7ef64e3450901648794d. --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 60531d5a..4d09065e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,5 @@ language: objective-c osx_image: xcode7 -xcode_sdk: - - iphonesimulator9.0 before_install: - brew update - brew reinstall xctool From 70c5582af7c6ff41c7fdf82567c588c99ff0c0dc Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Sat, 19 Sep 2015 11:14:45 -0700 Subject: [PATCH 18/60] Bump SDK in build.sh --- build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 55980eb7..2c0bc6da 100755 --- a/build.sh +++ b/build.sh @@ -1,8 +1,8 @@ #!/bin/bash # **** Update me when new Xcode versions are released! **** -PLATFORM="platform=iOS Simulator,OS=8.1,name=iPhone 6" -SDK="iphonesimulator8.1" +PLATFORM="platform=iOS Simulator,OS=9.0,name=iPhone 6" +SDK="iphonesimulator9.0" # It is pitch black. From 3f12162b1f3dcaab7f31ad856db5907844cda1e3 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Sat, 19 Sep 2015 11:14:45 -0700 Subject: [PATCH 19/60] Bump SDK in build.sh --- build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 55980eb7..2c0bc6da 100755 --- a/build.sh +++ b/build.sh @@ -1,8 +1,8 @@ #!/bin/bash # **** Update me when new Xcode versions are released! **** -PLATFORM="platform=iOS Simulator,OS=8.1,name=iPhone 6" -SDK="iphonesimulator8.1" +PLATFORM="platform=iOS Simulator,OS=9.0,name=iPhone 6" +SDK="iphonesimulator9.0" # It is pitch black. From a14267ebf207852494ac9e2f8b1cbceab00c3952 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Wed, 16 Sep 2015 17:03:33 -0700 Subject: [PATCH 20/60] Bump the .travis.yml OS X image requirement for Xcode 7 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 8899c440..34d81c0e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: objective-c +osx_image: xcode7 before_install: - brew update - brew reinstall xctool From a1236a90c1068cec339ed8eaf2c60f01f258cd3b Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Sat, 19 Sep 2015 13:10:40 -0700 Subject: [PATCH 21/60] Update Swift example --- examples/Swift/Sample.xcodeproj/project.pbxproj | 1 + examples/Swift/Sample/ViewController.swift | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/Swift/Sample.xcodeproj/project.pbxproj b/examples/Swift/Sample.xcodeproj/project.pbxproj index 36632d7d..10ad4f73 100644 --- a/examples/Swift/Sample.xcodeproj/project.pbxproj +++ b/examples/Swift/Sample.xcodeproj/project.pbxproj @@ -129,6 +129,7 @@ 050E7C6619D22E19004363C2 /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftUpdateCheck = 0700; LastUpgradeCheck = 0600; ORGANIZATIONNAME = Facebook; TargetAttributes = { diff --git a/examples/Swift/Sample/ViewController.swift b/examples/Swift/Sample/ViewController.swift index 9801a205..037e0965 100644 --- a/examples/Swift/Sample/ViewController.swift +++ b/examples/Swift/Sample/ViewController.swift @@ -27,7 +27,7 @@ class ViewController: UIViewController, ASTableViewDataSource, ASTableViewDelega self.tableView.asyncDelegate = self } - required init(coder aDecoder: NSCoder) { + required init?(coder aDecoder: NSCoder) { fatalError("storyboards are incompatible with truth and beauty") } From 441a0e6928b8f55453936118422ff6768e71ab9d Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Sun, 20 Sep 2015 22:32:04 -0700 Subject: [PATCH 22/60] Update types for drawParameters --- AsyncDisplayKit/ASDisplayNode+Subclasses.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode+Subclasses.h b/AsyncDisplayKit/ASDisplayNode+Subclasses.h index 3ecd08e1..7f94e3f2 100644 --- a/AsyncDisplayKit/ASDisplayNode+Subclasses.h +++ b/AsyncDisplayKit/ASDisplayNode+Subclasses.h @@ -193,7 +193,7 @@ NS_ASSUME_NONNULL_BEGIN * @note Called on the display queue and/or main queue (MUST BE THREAD SAFE) */ + (void)drawRect:(CGRect)bounds - withParameters:(id)parameters + withParameters:(nullable id)parameters isCancelled:(asdisplaynode_iscancelled_block_t)isCancelledBlock isRasterizing:(BOOL)isRasterizing; @@ -210,7 +210,7 @@ NS_ASSUME_NONNULL_BEGIN * * @note Called on the display queue and/or main queue (MUST BE THREAD SAFE) */ -+ (nullable UIImage *)displayWithParameters:(id)parameters ++ (nullable UIImage *)displayWithParameters:(nullable id)parameters isCancelled:(asdisplaynode_iscancelled_block_t)isCancelledBlock; /** @@ -220,7 +220,7 @@ NS_ASSUME_NONNULL_BEGIN * * @note Called on the main thread only */ -- (NSObject *)drawParametersForAsyncLayer:(_ASDisplayLayer *)layer; +- (nullable id)drawParametersForAsyncLayer:(_ASDisplayLayer *)layer; /** * @abstract Indicates that the receiver is about to display. From 73af8f1c8b382c5911dcb5af9deeb68a27ef3497 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Sat, 26 Sep 2015 18:05:12 -0700 Subject: [PATCH 23/60] Simplify ASImageIdentifier definition --- AsyncDisplayKit/ASMultiplexImageNode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsyncDisplayKit/ASMultiplexImageNode.h b/AsyncDisplayKit/ASMultiplexImageNode.h index d395d962..9c280768 100644 --- a/AsyncDisplayKit/ASMultiplexImageNode.h +++ b/AsyncDisplayKit/ASMultiplexImageNode.h @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN @protocol ASMultiplexImageNodeDelegate; @protocol ASMultiplexImageNodeDataSource; -typedef __kindof NSObject * ASImageIdentifier; +typedef id ASImageIdentifier; extern NSString *const ASMultiplexImageNodeErrorDomain; From ee970d412b70ca1681cb1a981f84d130905c5796 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Mon, 5 Oct 2015 13:48:09 -0700 Subject: [PATCH 24/60] Annotate ASCollectionViewProtocols.h --- AsyncDisplayKit/ASCollectionViewProtocols.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionViewProtocols.h b/AsyncDisplayKit/ASCollectionViewProtocols.h index 0f0b5ed7..5c4bcf96 100644 --- a/AsyncDisplayKit/ASCollectionViewProtocols.h +++ b/AsyncDisplayKit/ASCollectionViewProtocols.h @@ -6,6 +6,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ +NS_ASSUME_NONNULL_BEGIN + /** * This is a subset of UICollectionViewDataSource. * @@ -50,7 +52,9 @@ - (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath; - (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath; -- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender; -- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender; +- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender; +- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender; @end + +NS_ASSUME_NONNULL_END From fb0341215f34d0b49e1346a690a9510f2c820d2b Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Tue, 13 Oct 2015 21:27:18 -0700 Subject: [PATCH 25/60] Fix nullability in MultiplexImageNodeDataSource --- AsyncDisplayKit/ASMultiplexImageNode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsyncDisplayKit/ASMultiplexImageNode.h b/AsyncDisplayKit/ASMultiplexImageNode.h index 2178893f..31e22763 100644 --- a/AsyncDisplayKit/ASMultiplexImageNode.h +++ b/AsyncDisplayKit/ASMultiplexImageNode.h @@ -225,7 +225,7 @@ didFinishDownloadingImageWithIdentifier:(ASImageIdentifier)imageIdentifier * @note This method may be called from any thread. * @return A PHAsset corresponding to `assetLocalIdentifier`, or nil if none is available. */ -- (PHAsset *)multiplexImageNode:(ASMultiplexImageNode *)imageNode assetForLocalIdentifier:(NSString *)assetLocalIdentifier; +- (nullable PHAsset *)multiplexImageNode:(ASMultiplexImageNode *)imageNode assetForLocalIdentifier:(NSString *)assetLocalIdentifier; @end From 0e90d0556f0d9e9fe3e08147f8d4ed54e5841fe2 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Wed, 28 Oct 2015 21:15:14 -0700 Subject: [PATCH 26/60] Fix UIView+ASConvenience.h merge --- AsyncDisplayKit/Details/UIView+ASConvenience.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AsyncDisplayKit/Details/UIView+ASConvenience.h b/AsyncDisplayKit/Details/UIView+ASConvenience.h index 43b8a1a7..4557d9b8 100644 --- a/AsyncDisplayKit/Details/UIView+ASConvenience.h +++ b/AsyncDisplayKit/Details/UIView+ASConvenience.h @@ -80,3 +80,5 @@ NS_ASSUME_NONNULL_BEGIN @property (nullable, nonatomic, copy) NSString *accessibilityIdentifier; @end + +NS_ASSUME_NONNULL_END From f2a095a4591e3ae455b7916e0d2f5f4c8defbeb0 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Wed, 28 Oct 2015 21:18:13 -0700 Subject: [PATCH 27/60] Fix test build by casting test image identifiers --- AsyncDisplayKitTests/ASMultiplexImageNodeTests.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AsyncDisplayKitTests/ASMultiplexImageNodeTests.m b/AsyncDisplayKitTests/ASMultiplexImageNodeTests.m index a08173d5..069b545d 100644 --- a/AsyncDisplayKitTests/ASMultiplexImageNodeTests.m +++ b/AsyncDisplayKitTests/ASMultiplexImageNodeTests.m @@ -278,7 +278,7 @@ static BOOL ASRunRunLoopUntilBlockIsTrue(BOOL (^block)()) return; // Bail if it's trying to load an identifier that's more than one step than what's loaded. - NSInteger nextImageIdentifier = [imageNode.loadedImageIdentifier integerValue] + 1; + NSInteger nextImageIdentifier = [(NSNumber *)imageNode.loadedImageIdentifier integerValue] + 1; if (requestedIdentifierValue != nextImageIdentifier) return; @@ -344,7 +344,7 @@ static BOOL ASRunRunLoopUntilBlockIsTrue(BOOL (^block)()) // Wait until the image is loaded. ASRunRunLoopUntilBlockIsTrue(^BOOL{ - return [imageNode.loadedImageIdentifier isEqual:imageIdentifier]; + return [(id)imageNode.loadedImageIdentifier isEqual:imageIdentifier]; }); // Verify the delegation. From 82c1549d8f1dbaa0ac9ea8653a3476059bb99d24 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Thu, 29 Oct 2015 09:57:27 -0700 Subject: [PATCH 28/60] Fix nullability of ASDisplayNode.name --- AsyncDisplayKit/ASDisplayNode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index 12acd996..09d57a50 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -113,7 +113,7 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); /** * @abstract The name of this node, which will be displayed in `description`. The default value is nil. */ -@property (atomic, copy) NSString *name; +@property (nullable, atomic, copy) NSString *name; /** * @abstract Returns whether the node is synchronous. From bfe3040f5745f2cc718e166835f51d2312164b46 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Mon, 9 Nov 2015 10:10:37 -0800 Subject: [PATCH 29/60] Update nullability in ASCellNode.h --- AsyncDisplayKit/ASCellNode.h | 8 ++++---- AsyncDisplayKit/ASCellNode.m | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/AsyncDisplayKit/ASCellNode.h b/AsyncDisplayKit/ASCellNode.h index c7a5e604..c42b1a08 100644 --- a/AsyncDisplayKit/ASCellNode.h +++ b/AsyncDisplayKit/ASCellNode.h @@ -87,10 +87,10 @@ typedef NSUInteger ASCellNodeAnimation; * ASCellNode must forward touch events in order for UITableView and UICollectionView tap handling to work. Overriding * these methods (e.g. for highlighting) requires the super method be called. */ -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; +- (void)touchesBegan:(NSSet *)touches withEvent:(nullable UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; +- (void)touchesMoved:(NSSet *)touches withEvent:(nullable UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; +- (void)touchesEnded:(NSSet *)touches withEvent:(nullable UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; +- (void)touchesCancelled:(NSSet *)touches withEvent:(nullable UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; /** * Marks the node as needing layout. Convenience for use whether the view / layer is loaded or not. Safe to call from a background thread. diff --git a/AsyncDisplayKit/ASCellNode.m b/AsyncDisplayKit/ASCellNode.m index a56e9f35..3881aff9 100644 --- a/AsyncDisplayKit/ASCellNode.m +++ b/AsyncDisplayKit/ASCellNode.m @@ -113,7 +113,8 @@ static const CGFloat kFontSize = 18.0f; { if (!(self = [super init])) return nil; - + + _text = @""; _textNode = [[ASTextNode alloc] init]; [self addSubnode:_textNode]; From 057e98380e18a2c0fb781e6b58ef6d55f433ec65 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Fri, 13 Nov 2015 12:02:09 -0800 Subject: [PATCH 30/60] Add NSObjectProtocol requirement to ASImageIdentifier --- AsyncDisplayKit/ASMultiplexImageNode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsyncDisplayKit/ASMultiplexImageNode.h b/AsyncDisplayKit/ASMultiplexImageNode.h index b6c6e97b..25e463b2 100644 --- a/AsyncDisplayKit/ASMultiplexImageNode.h +++ b/AsyncDisplayKit/ASMultiplexImageNode.h @@ -16,7 +16,7 @@ NS_ASSUME_NONNULL_BEGIN @protocol ASMultiplexImageNodeDelegate; @protocol ASMultiplexImageNodeDataSource; -typedef id ASImageIdentifier; +typedef id ASImageIdentifier; extern NSString *const ASMultiplexImageNodeErrorDomain; From 7922895b60f6d07cc167c22a2e341a91ef298c84 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Fri, 13 Nov 2015 12:11:24 -0800 Subject: [PATCH 31/60] (Re?)add type annotations on touchesBegan:withEvent: et al --- AsyncDisplayKit/ASCellNode.h | 8 ++++---- AsyncDisplayKit/ASDisplayNode+Subclasses.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/AsyncDisplayKit/ASCellNode.h b/AsyncDisplayKit/ASCellNode.h index 04c0b71e..4877824d 100644 --- a/AsyncDisplayKit/ASCellNode.h +++ b/AsyncDisplayKit/ASCellNode.h @@ -78,10 +78,10 @@ typedef NSUInteger ASCellNodeAnimation; * ASCellNode must forward touch events in order for UITableView and UICollectionView tap handling to work. Overriding * these methods (e.g. for highlighting) requires the super method be called. */ -- (void)touchesBegan:(NSSet *)touches withEvent:(nullable UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; -- (void)touchesMoved:(NSSet *)touches withEvent:(nullable UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; -- (void)touchesEnded:(NSSet *)touches withEvent:(nullable UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; -- (void)touchesCancelled:(NSSet *)touches withEvent:(nullable UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; +- (void)touchesBegan:(NSSet *)touches withEvent:(nullable UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; +- (void)touchesMoved:(NSSet *)touches withEvent:(nullable UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; +- (void)touchesEnded:(NSSet *)touches withEvent:(nullable UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; +- (void)touchesCancelled:(NSSet *)touches withEvent:(nullable UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; /** * Marks the node as needing layout. Convenience for use whether the view / layer is loaded or not. diff --git a/AsyncDisplayKit/ASDisplayNode+Subclasses.h b/AsyncDisplayKit/ASDisplayNode+Subclasses.h index b1b2ac10..0a8e4be5 100644 --- a/AsyncDisplayKit/ASDisplayNode+Subclasses.h +++ b/AsyncDisplayKit/ASDisplayNode+Subclasses.h @@ -307,7 +307,7 @@ NS_ASSUME_NONNULL_BEGIN * @param touches A set of UITouch instances. * @param event A UIEvent associated with the touch. */ -- (void)touchesBegan:(NSSet *)touches withEvent:(nullable UIEvent *)event; +- (void)touchesBegan:(NSSet *)touches withEvent:(nullable UIEvent *)event; /** * @abstract Tells the node when touches moved in its view. @@ -315,7 +315,7 @@ NS_ASSUME_NONNULL_BEGIN * @param touches A set of UITouch instances. * @param event A UIEvent associated with the touch. */ -- (void)touchesMoved:(NSSet *)touches withEvent:(nullable UIEvent *)event; +- (void)touchesMoved:(NSSet *)touches withEvent:(nullable UIEvent *)event; /** * @abstract Tells the node when touches ended in its view. @@ -323,7 +323,7 @@ NS_ASSUME_NONNULL_BEGIN * @param touches A set of UITouch instances. * @param event A UIEvent associated with the touch. */ -- (void)touchesEnded:(NSSet *)touches withEvent:(nullable UIEvent *)event; +- (void)touchesEnded:(NSSet *)touches withEvent:(nullable UIEvent *)event; /** * @abstract Tells the node when touches was cancelled in its view. @@ -331,7 +331,7 @@ NS_ASSUME_NONNULL_BEGIN * @param touches A set of UITouch instances. * @param event A UIEvent associated with the touch. */ -- (void)touchesCancelled:(NSSet *)touches withEvent:(nullable UIEvent *)event; +- (void)touchesCancelled:(NSSet *)touches withEvent:(nullable UIEvent *)event; /** @name Managing Gesture Recognizers */ From ab326fc683ddf478d5d5b262671f9bb520045050 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Fri, 13 Nov 2015 12:17:17 -0800 Subject: [PATCH 32/60] touchesCancelled:withEvent: has a nullable touches argument in UIKit for some reason --- AsyncDisplayKit/ASCellNode.h | 2 +- AsyncDisplayKit/ASDisplayNode+Subclasses.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AsyncDisplayKit/ASCellNode.h b/AsyncDisplayKit/ASCellNode.h index 4877824d..54138de0 100644 --- a/AsyncDisplayKit/ASCellNode.h +++ b/AsyncDisplayKit/ASCellNode.h @@ -81,7 +81,7 @@ typedef NSUInteger ASCellNodeAnimation; - (void)touchesBegan:(NSSet *)touches withEvent:(nullable UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; - (void)touchesMoved:(NSSet *)touches withEvent:(nullable UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; - (void)touchesEnded:(NSSet *)touches withEvent:(nullable UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; -- (void)touchesCancelled:(NSSet *)touches withEvent:(nullable UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; +- (void)touchesCancelled:(nullable NSSet *)touches withEvent:(nullable UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; /** * Marks the node as needing layout. Convenience for use whether the view / layer is loaded or not. diff --git a/AsyncDisplayKit/ASDisplayNode+Subclasses.h b/AsyncDisplayKit/ASDisplayNode+Subclasses.h index 0a8e4be5..e52a37bf 100644 --- a/AsyncDisplayKit/ASDisplayNode+Subclasses.h +++ b/AsyncDisplayKit/ASDisplayNode+Subclasses.h @@ -331,7 +331,7 @@ NS_ASSUME_NONNULL_BEGIN * @param touches A set of UITouch instances. * @param event A UIEvent associated with the touch. */ -- (void)touchesCancelled:(NSSet *)touches withEvent:(nullable UIEvent *)event; +- (void)touchesCancelled:(nullable NSSet *)touches withEvent:(nullable UIEvent *)event; /** @name Managing Gesture Recognizers */ From 628bb7eb3add06d5d12050a18b27e44a5bbfb76f Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Tue, 24 Nov 2015 16:43:40 -0800 Subject: [PATCH 33/60] Revert minor deletion --- AsyncDisplayKit/Details/ASLayoutController.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AsyncDisplayKit/Details/ASLayoutController.h b/AsyncDisplayKit/Details/ASLayoutController.h index a52f24fe..22e4b12a 100644 --- a/AsyncDisplayKit/Details/ASLayoutController.h +++ b/AsyncDisplayKit/Details/ASLayoutController.h @@ -14,6 +14,8 @@ NS_ASSUME_NONNULL_BEGIN +@class ASCellNode; + typedef struct { CGFloat leadingBufferScreenfuls; CGFloat trailingBufferScreenfuls; From 8e75c594c730c0cb1b7bf226ab6f11003c71886b Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Tue, 1 Dec 2015 16:48:55 -0800 Subject: [PATCH 34/60] Add some more annotations --- AsyncDisplayKit/ASDisplayNodeExtras.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNodeExtras.h b/AsyncDisplayKit/ASDisplayNodeExtras.h index 3cc9abb0..b387b374 100644 --- a/AsyncDisplayKit/ASDisplayNodeExtras.h +++ b/AsyncDisplayKit/ASDisplayNodeExtras.h @@ -37,17 +37,17 @@ extern ASDisplayNode *ASDisplayNodeUltimateParentOfNode(ASDisplayNode *node); In the event that a node's backing layer is not created yet, the function will only walk the direct subnodes instead of forcing the layer heirarchy to be created. */ -extern void ASDisplayNodePerformBlockOnEveryNode(CALayer *layer, ASDisplayNode *node, void(^block)(ASDisplayNode *node)); +extern void ASDisplayNodePerformBlockOnEveryNode(CALayer * _Nullable layer, ASDisplayNode * _Nullable node, void(^block)(ASDisplayNode *node)); /** Given a display node, traverses up the layer tree hierarchy, returning the first display node that passes block. */ -extern id ASDisplayNodeFind(ASDisplayNode * _Nullable node, BOOL (^block)(ASDisplayNode *node)); +extern id _Nullable ASDisplayNodeFind(ASDisplayNode * _Nullable node, BOOL (^block)(ASDisplayNode *node)); /** Given a display node, traverses up the layer tree hierarchy, returning the first display node of kind class. */ -extern id ASDisplayNodeFindClass(ASDisplayNode *start, Class c); +extern id _Nullable ASDisplayNodeFindClass(ASDisplayNode *start, Class c); /** * Given two nodes, finds their most immediate common parent. Used for geometry conversion methods. From 1fd65c2f254f1f7d60833f1fbf8fa3d7267e8f1d Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Tue, 1 Dec 2015 21:57:45 -0800 Subject: [PATCH 35/60] Annotate ASAsciiArtBoxCreator.h --- AsyncDisplayKit/Layout/ASAsciiArtBoxCreator.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/AsyncDisplayKit/Layout/ASAsciiArtBoxCreator.h b/AsyncDisplayKit/Layout/ASAsciiArtBoxCreator.h index 15d825a5..18a925a7 100644 --- a/AsyncDisplayKit/Layout/ASAsciiArtBoxCreator.h +++ b/AsyncDisplayKit/Layout/ASAsciiArtBoxCreator.h @@ -10,6 +10,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + @protocol ASLayoutableAsciiArtProtocol /** * Returns an ascii-art representation of this object and its children. @@ -41,7 +43,7 @@ * | ASTextNode ASTextNode ASTextNode | * ---------------------------------------- */ -+ (NSString *)horizontalBoxStringForChildren:(NSArray *)children parent:(NSString *)parent; ++ (NSString *)horizontalBoxStringForChildren:(NSArray *)children parent:(NSString *)parent; /** * Renders an ascii art box with the children aligned vertically. @@ -52,8 +54,8 @@ * | ASTextNode | * --------------------- */ -+ (NSString *)verticalBoxStringForChildren:(NSArray *)children parent:(NSString *)parent; ++ (NSString *)verticalBoxStringForChildren:(NSArray *)children parent:(NSString *)parent; @end - +NS_ASSUME_NONNULL_END From e202b18db9ac7d01640a16a573e0cb6c681c6ec4 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Sun, 13 Dec 2015 10:07:14 -0800 Subject: [PATCH 36/60] Annotate some new stuff --- AsyncDisplayKit/ASMapNode.h | 8 ++++++-- AsyncDisplayKit/Private/ASDisplayNode+FrameworkPrivate.h | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/AsyncDisplayKit/ASMapNode.h b/AsyncDisplayKit/ASMapNode.h index e5fcbd49..eb450b1c 100644 --- a/AsyncDisplayKit/ASMapNode.h +++ b/AsyncDisplayKit/ASMapNode.h @@ -9,6 +9,8 @@ #import #import +NS_ASSUME_NONNULL_BEGIN + @interface ASMapNode : ASImageNode - (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate NS_DESIGNATED_INITIALIZER; @@ -16,7 +18,7 @@ /** 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. */ -@property (nonatomic, readonly) MKMapView *mapView; +@property (nullable, nonatomic, readonly) MKMapView *mapView; /** Set this to YES to turn the snapshot into an interactive MKMapView and vice versa. Defaults to NO. @@ -38,6 +40,8 @@ * @discussion This method set the annotations of the static map view and also to the live map view. Passing an empty array clears the map of any annotations. * @param annotations An array of objects that conform to the MKAnnotation protocol */ -- (void)setAnnotations:(NSArray *)annotations; +- (void)setAnnotations:(NSArray> *)annotations; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Private/ASDisplayNode+FrameworkPrivate.h b/AsyncDisplayKit/Private/ASDisplayNode+FrameworkPrivate.h index 58cc12c3..dcc2ea26 100644 --- a/AsyncDisplayKit/Private/ASDisplayNode+FrameworkPrivate.h +++ b/AsyncDisplayKit/Private/ASDisplayNode+FrameworkPrivate.h @@ -19,6 +19,8 @@ #import "ASThread.h" #import "ASLayoutOptions.h" +NS_ASSUME_NONNULL_BEGIN + /** Hierarchy state is propogated from nodes to all of their children when certain behaviors are required from the subtree. Examples include rasterization and external driving of the .interfaceState property. @@ -101,9 +103,11 @@ typedef NS_OPTIONS(NSUInteger, ASHierarchyState) @end @interface UIView (ASDisplayNodeInternal) -@property (nonatomic, assign, readwrite) ASDisplayNode *asyncdisplaykit_node; +@property (nullable, nonatomic, assign, readwrite) ASDisplayNode *asyncdisplaykit_node; @end @interface CALayer (ASDisplayNodeInternal) -@property (nonatomic, assign, readwrite) ASDisplayNode *asyncdisplaykit_node; +@property (nullable, nonatomic, assign, readwrite) ASDisplayNode *asyncdisplaykit_node; @end + +NS_ASSUME_NONNULL_END From d7b128e19bb00fcc4d8c5b6aec60215cb50edc1c Mon Sep 17 00:00:00 2001 From: Rajinder Ramgarhia Date: Sun, 20 Dec 2015 21:25:59 -0500 Subject: [PATCH 37/60] ASButtonNode content alignement properties --- AsyncDisplayKit.xcodeproj/project.pbxproj | 17 ++++++++++++++++- AsyncDisplayKit/ASButtonNode.h | 11 +++++++++++ AsyncDisplayKit/ASButtonNode.mm | 4 ++-- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 2e0296d3..c07972fc 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -1523,7 +1523,7 @@ 058D09B9195D04C000B7D73C /* Frameworks */, 058D09BA195D04C000B7D73C /* Resources */, 3B9D88CDF51B429C8409E4B6 /* Copy Pods Resources */, - 1B86F48711505F91D5FEF571 /* Embed Pods Frameworks */, + 5ADEA7587189397768F2B36C /* Embed Pods Frameworks */, ); buildRules = ( ); @@ -1668,6 +1668,21 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; + 5ADEA7587189397768F2B36C /* 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-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/AsyncDisplayKit/ASButtonNode.h b/AsyncDisplayKit/ASButtonNode.h index bf2227ea..55b3948f 100644 --- a/AsyncDisplayKit/ASButtonNode.h +++ b/AsyncDisplayKit/ASButtonNode.h @@ -31,6 +31,17 @@ typedef enum : NSUInteger { */ @property (nonatomic, assign) BOOL laysOutHorizontally; +/** Horizontally align content(text or image). + Defaults to ASAlignmentMiddle. + */ +@property (nonatomic, assign) ASHorizontalAlignment contentHorizontalAlignment; + +/** Vertically align content(text or image). + Defaults to ASAlignmentCenter. + */ +@property (nonatomic, assign) ASVerticalAlignment contentVerticalAlignment; + + - (NSAttributedString *)attributedTitleForState:(ASButtonState)state; - (void)setAttributedTitle:(NSAttributedString *)title forState:(ASButtonState)state; diff --git a/AsyncDisplayKit/ASButtonNode.mm b/AsyncDisplayKit/ASButtonNode.mm index 1801a035..17431576 100644 --- a/AsyncDisplayKit/ASButtonNode.mm +++ b/AsyncDisplayKit/ASButtonNode.mm @@ -195,8 +195,8 @@ ASStackLayoutSpec *stack = [[ASStackLayoutSpec alloc] init]; stack.direction = self.laysOutHorizontally ? ASStackLayoutDirectionHorizontal : ASStackLayoutDirectionVertical; stack.spacing = self.contentSpacing; - stack.justifyContent = ASStackLayoutJustifyContentCenter; - stack.alignItems = ASStackLayoutAlignItemsCenter; + stack.horizontalAlignment = self.contentHorizontalAlignment ? self.contentHorizontalAlignment : ASAlignmentMiddle; + stack.verticalAlignment = self.contentVerticalAlignment ? self.contentVerticalAlignment : ASAlignmentCenter; NSMutableArray *children = [[NSMutableArray alloc] initWithCapacity:2]; if (self.imageNode.image) { From 108ce6d8fcfbf394d8bfca740060cc9176b3224c Mon Sep 17 00:00:00 2001 From: Rajinder Ramgarhia Date: Mon, 21 Dec 2015 10:03:32 -0500 Subject: [PATCH 38/60] Set horizontal & vertical alignment default to center. Use ivar to set layout. --- AsyncDisplayKit/ASButtonNode.h | 4 ++-- AsyncDisplayKit/ASButtonNode.mm | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/AsyncDisplayKit/ASButtonNode.h b/AsyncDisplayKit/ASButtonNode.h index 55b3948f..57b7caf1 100644 --- a/AsyncDisplayKit/ASButtonNode.h +++ b/AsyncDisplayKit/ASButtonNode.h @@ -31,12 +31,12 @@ typedef enum : NSUInteger { */ @property (nonatomic, assign) BOOL laysOutHorizontally; -/** Horizontally align content(text or image). +/** Horizontally align content (text or image). Defaults to ASAlignmentMiddle. */ @property (nonatomic, assign) ASHorizontalAlignment contentHorizontalAlignment; -/** Vertically align content(text or image). +/** Vertically align content (text or image). Defaults to ASAlignmentCenter. */ @property (nonatomic, assign) ASVerticalAlignment contentVerticalAlignment; diff --git a/AsyncDisplayKit/ASButtonNode.mm b/AsyncDisplayKit/ASButtonNode.mm index 17431576..196216a6 100644 --- a/AsyncDisplayKit/ASButtonNode.mm +++ b/AsyncDisplayKit/ASButtonNode.mm @@ -39,6 +39,9 @@ _titleNode = [[ASTextNode alloc] init]; _imageNode = [[ASImageNode alloc] init]; + _contentHorizontalAlignment = ASAlignmentMiddle; + _contentVerticalAlignment = ASAlignmentCenter; + [self addSubnode:_titleNode]; [self addSubnode:_imageNode]; @@ -195,8 +198,8 @@ ASStackLayoutSpec *stack = [[ASStackLayoutSpec alloc] init]; stack.direction = self.laysOutHorizontally ? ASStackLayoutDirectionHorizontal : ASStackLayoutDirectionVertical; stack.spacing = self.contentSpacing; - stack.horizontalAlignment = self.contentHorizontalAlignment ? self.contentHorizontalAlignment : ASAlignmentMiddle; - stack.verticalAlignment = self.contentVerticalAlignment ? self.contentVerticalAlignment : ASAlignmentCenter; + stack.horizontalAlignment = _contentHorizontalAlignment; + stack.verticalAlignment = _contentVerticalAlignment; NSMutableArray *children = [[NSMutableArray alloc] initWithCapacity:2]; if (self.imageNode.image) { From 065625f246f09075c12840869ec01215773c0395 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Tue, 22 Dec 2015 21:46:46 -0800 Subject: [PATCH 39/60] Make ASCollectionView always create an ASCollectionNode. Add visibilityDidChange:, interfaceStateDidChange:fromState: --- AsyncDisplayKit/ASCollectionNode.m | 11 +- AsyncDisplayKit/ASCollectionView.h | 36 ++--- AsyncDisplayKit/ASCollectionView.mm | 130 +++++++++--------- AsyncDisplayKit/ASDisplayNode+Subclasses.h | 123 ++++++++--------- AsyncDisplayKit/ASDisplayNode.mm | 14 +- AsyncDisplayKit/ASViewController.h | 11 +- AsyncDisplayKit/ASViewController.m | 5 + .../Private/ASDisplayNode+FrameworkPrivate.h | 3 + .../Sample.xcodeproj/project.pbxproj | 16 --- 9 files changed, 180 insertions(+), 169 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionNode.m b/AsyncDisplayKit/ASCollectionNode.m index cd0b7367..eb0ddd30 100644 --- a/AsyncDisplayKit/ASCollectionNode.m +++ b/AsyncDisplayKit/ASCollectionNode.m @@ -9,6 +9,10 @@ #import "ASCollectionNode.h" #import "ASDisplayNode+Subclasses.h" +@interface ASCollectionView (Internal) +- (ASCollectionView *)_initWithCollectionViewLayout:(UICollectionViewLayout *)layout; +@end + @implementation ASCollectionNode - (instancetype)init @@ -20,7 +24,7 @@ - (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout { - if (self = [super initWithViewBlock:^UIView *{ return [[ASCollectionView alloc] initWithCollectionViewLayout:layout]; }]) { + if (self = [super initWithViewBlock:^UIView *{ return [[ASCollectionView alloc] _initWithCollectionViewLayout:layout]; }]) { return self; } return nil; @@ -31,6 +35,11 @@ return (ASCollectionView *)[super view]; } +- (void)visibilityDidChange:(BOOL)isVisible +{ + +} + - (void)clearContents { [super clearContents]; diff --git a/AsyncDisplayKit/ASCollectionView.h b/AsyncDisplayKit/ASCollectionView.h index 31b3722d..8d715e3e 100644 --- a/AsyncDisplayKit/ASCollectionView.h +++ b/AsyncDisplayKit/ASCollectionView.h @@ -12,7 +12,7 @@ #import #import #import - +#import @class ASCellNode; @protocol ASCollectionViewDataSource; @@ -27,6 +27,11 @@ */ @interface ASCollectionView : UICollectionView +/** + * Initializer. + * + * @param layout The layout object to use for organizing items. The collection view stores a strong reference to the specified object. Must not be nil. + */ - (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout; @property (nonatomic, weak) id asyncDataSource; @@ -52,27 +57,6 @@ */ - (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType; -/** - * Initializer. - * - * @param frame The frame rectangle for the collection view, measured in points. The origin of the frame is relative to the superview - * in which you plan to add it. This frame is passed to the superclass during initialization. - * - * @param layout The layout object to use for organizing items. The collection view stores a strong reference to the specified object. - * Must not be nil. - * - * @param asyncDataFetchingEnabled Enable the data fetching in async mode. - * - * @discussion If asyncDataFetching is enabled, the `ASCollectionView` will fetch data through `collectionView:numberOfRowsInSection:` and - * `collectionView:nodeForRowAtIndexPath:` in async mode from background thread. Otherwise, the methods will be invoked synchronically - * from calling thread. - * Enabling asyncDataFetching could avoid blocking main thread for `ASCellNode` allocation, which is frequently reported issue for - * large scale data. On another hand, the application code need take the responsibility to avoid data inconsistence. Specifically, - * we will lock the data source through `collectionViewLockDataSource`, and unlock it by `collectionViewUnlockDataSource` after the data fetching. - * The application should not update the data source while the data source is locked, to keep data consistence. - */ -- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout asyncDataFetching:(BOOL)asyncDataFetchingEnabled; - /** * The number of screens left to scroll before the delegate -collectionView:beginBatchFetchingWithContext: is called. * @@ -429,4 +413,10 @@ */ - (CGSize)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section; -@end \ No newline at end of file +@end + +@interface ASCollectionView (Deprecated) + +- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout asyncDataFetching:(BOOL)asyncDataFetchingEnabled ASDISPLAYNODE_DEPRECATED; + +@end diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index ffd1c660..0aeefb27 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -9,6 +9,7 @@ #import "ASAssert.h" #import "ASBatchFetching.h" #import "ASCollectionView.h" +#import "ASCollectionNode.h" #import "ASCollectionDataController.h" #import "ASCollectionViewLayoutController.h" #import "ASCollectionViewFlowLayoutInspector.h" @@ -31,7 +32,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; */ static BOOL _isInterceptedSelector(SEL sel) { - return ( + return ( // handled by ASCollectionView node<->cell machinery sel == @selector(collectionView:cellForItemAtIndexPath:) || sel == @selector(collectionView:layout:sizeForItemAtIndexPath:) || @@ -44,7 +45,7 @@ static BOOL _isInterceptedSelector(SEL sel) // used for ASRangeController visibility updates sel == @selector(collectionView:willDisplayCell:forItemAtIndexPath:) || sel == @selector(collectionView:didEndDisplayingCell:forItemAtIndexPath:) || - + // used for batch fetching API sel == @selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:) ); @@ -70,7 +71,7 @@ static BOOL _isInterceptedSelector(SEL sel) if (!self) { return nil; } - + ASDisplayNodeAssert(target, @"target must not be nil"); ASDisplayNodeAssert(interceptor, @"interceptor must not be nil"); @@ -84,7 +85,7 @@ static BOOL _isInterceptedSelector(SEL sel) { ASDisplayNodeAssert(_target, @"target must not be nil"); // catch weak ref's being nilled early ASDisplayNodeAssert(_interceptor, @"interceptor must not be nil"); - + return (_isInterceptedSelector(aSelector) || [_target respondsToSelector:aSelector]); } @@ -92,7 +93,7 @@ static BOOL _isInterceptedSelector(SEL sel) { ASDisplayNodeAssert(_target, @"target must not be nil"); // catch weak ref's being nilled early ASDisplayNodeAssert(_interceptor, @"interceptor must not be nil"); - + if (_isInterceptedSelector(aSelector)) { return _interceptor; } @@ -140,21 +141,21 @@ static BOOL _isInterceptedSelector(SEL sel) @interface ASCollectionView () { _ASCollectionViewProxy *_proxyDataSource; _ASCollectionViewProxy *_proxyDelegate; - + ASCollectionDataController *_dataController; ASRangeController *_rangeController; ASCollectionViewLayoutController *_layoutController; ASCollectionViewFlowLayoutInspector *_flowLayoutInspector; - + BOOL _performingBatchUpdates; NSMutableArray *_batchUpdateBlocks; - + BOOL _asyncDataFetchingEnabled; BOOL _asyncDelegateImplementsInsetSection; BOOL _collectionViewLayoutImplementsInsetSection; BOOL _asyncDataSourceImplementsConstrainedSizeForNode; BOOL _queuedNodeSizeUpdate; - + ASBatchContext *_batchContext; CGSize _maxSizeForNodesConstrainedSize; @@ -172,7 +173,7 @@ static BOOL _isInterceptedSelector(SEL sel) * You will get an assertion failure saying `Invalid number of items in section 0. * The number of items after the update (1) must be equal to the number of items before the update (1) plus or minus the items added and removed (1 added, 0 removed).` * The collection view never queried your data source before the update to see that it actually had 0 items. - */ + */ BOOL _superIsPendingDataLoad; } @@ -187,48 +188,53 @@ static BOOL _isInterceptedSelector(SEL sel) - (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout { - return [self initWithFrame:CGRectZero collectionViewLayout:layout asyncDataFetching:NO]; + return [self initWithFrame:CGRectZero collectionViewLayout:layout]; } - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout { - return [self initWithFrame:frame collectionViewLayout:layout asyncDataFetching:NO]; +// ASCollectionNode *collectionNode = [[ASCollectionNode alloc] initWithCollectionViewLayout:layout]; +// collectionNode.frame = frame; +// return collectionNode.view; + return [self _initWithFrame:frame collectionViewLayout:layout]; } +// FIXME: This method is deprecated and will probably be removed in or shortly after 2.0. - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout asyncDataFetching:(BOOL)asyncDataFetchingEnabled +{ + return [self initWithFrame:frame collectionViewLayout:layout]; +} + +- (instancetype)_initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout { if (!(self = [super initWithFrame:frame collectionViewLayout:layout])) return nil; - // FIXME: asyncDataFetching is currently unreliable for some use cases. - // https://github.com/facebook/AsyncDisplayKit/issues/385 - asyncDataFetchingEnabled = NO; - _layoutController = [[ASCollectionViewLayoutController alloc] initWithCollectionView:self]; - + _rangeController = [[ASRangeController alloc] init]; _rangeController.dataSource = self; _rangeController.delegate = self; _rangeController.layoutController = _layoutController; - - _dataController = [[ASCollectionDataController alloc] initWithAsyncDataFetching:asyncDataFetchingEnabled]; + + _dataController = [[ASCollectionDataController alloc] initWithAsyncDataFetching:NO]; _dataController.delegate = _rangeController; _dataController.dataSource = self; _batchContext = [[ASBatchContext alloc] init]; - + _leadingScreensForBatching = 1.0; - - _asyncDataFetchingEnabled = asyncDataFetchingEnabled; + + _asyncDataFetchingEnabled = NO; _asyncDataSourceLocked = NO; - + _performingBatchUpdates = NO; _batchUpdateBlocks = [NSMutableArray array]; - + _superIsPendingDataLoad = YES; _collectionViewLayoutImplementsInsetSection = [layout respondsToSelector:@selector(sectionInset)]; - + _maxSizeForNodesConstrainedSize = self.bounds.size; // If the initial size is 0, expect a size change very soon which is part of the initial configuration // and should not trigger a relayout. @@ -262,13 +268,13 @@ static BOOL _isInterceptedSelector(SEL sel) */ - (ASCollectionViewFlowLayoutInspector *)flowLayoutInspector { - if (_flowLayoutInspector == nil) { - UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionViewLayout; - ASDisplayNodeAssertNotNil(layout, @"Collection view layout must be a flow layout to use the built-in inspector"); - _flowLayoutInspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:self - flowLayout:layout]; - } - return _flowLayoutInspector; + if (_flowLayoutInspector == nil) { + UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionViewLayout; + ASDisplayNodeAssertNotNil(layout, @"Collection view layout must be a flow layout to use the built-in inspector"); + _flowLayoutInspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:self + flowLayout:layout]; + } + return _flowLayoutInspector; } #pragma mark - @@ -314,7 +320,7 @@ static BOOL _isInterceptedSelector(SEL sel) // the (common) case of nilling the asyncDataSource in the ViewController's dealloc. In this case our _asyncDataSource // will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to nil out // super.dataSource in this case because calls to _ASTableViewProxy will start failing and cause crashes. - + if (asyncDataSource == nil) { super.dataSource = nil; _asyncDataSource = nil; @@ -334,7 +340,7 @@ static BOOL _isInterceptedSelector(SEL sel) // the (common) case of nilling the asyncDelegate in the ViewController's dealloc. In this case our _asyncDelegate // will return as nil (ARC magic) even though the _proxyDelegate still exists. It's really important to nil out // super.delegate in this case because calls to _ASTableViewProxy will start failing and cause crashes. - + if (asyncDelegate == nil) { // order is important here, the delegate must be callable while nilling super.delegate to avoid random crashes // in UIScrollViewAccessibility. @@ -348,7 +354,7 @@ static BOOL _isInterceptedSelector(SEL sel) super.delegate = (id)_proxyDelegate; _asyncDelegateImplementsInsetSection = ([_asyncDelegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)] ? 1 : 0); } - + [_layoutInspector didChangeCollectionViewDelegate:asyncDelegate]; } @@ -409,7 +415,7 @@ static BOOL _isInterceptedSelector(SEL sel) - (void)performBatchAnimated:(BOOL)animated updates:(void (^)())updates completion:(void (^)(BOOL))completion { ASDisplayNodeAssertMainThread(); - + [_dataController beginUpdates]; updates(); [_dataController endUpdatesAnimated:animated completion:completion]; @@ -487,7 +493,7 @@ static BOOL _isInterceptedSelector(SEL sel) - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { _ASCollectionViewCell *cell = [self dequeueReusableCellWithReuseIdentifier:kCellReuseIdentifier forIndexPath:indexPath]; - + ASCellNode *node = [_dataController nodeAtIndexPath:indexPath]; cell.node = node; [_rangeController configureContentView:cell.contentView forCellNode:node]; @@ -524,7 +530,7 @@ static BOOL _isInterceptedSelector(SEL sel) CGPoint scrollVelocity = [self.panGestureRecognizer velocityInView:self.superview]; return [self scrollDirectionForVelocity:scrollVelocity]; } - + - (ASScrollDirection)scrollDirectionForVelocity:(CGPoint)scrollVelocity { ASScrollDirection direction = ASScrollDirectionNone; @@ -544,7 +550,7 @@ static BOOL _isInterceptedSelector(SEL sel) direction |= ASScrollDirectionUp; } } - + return direction; } @@ -623,7 +629,7 @@ static BOOL _isInterceptedSelector(SEL sel) - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { [self handleBatchFetchScrollingToOffset:*targetContentOffset]; - + if ([_asyncDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) { [_asyncDelegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset]; } @@ -643,11 +649,11 @@ static BOOL _isInterceptedSelector(SEL sel) - (void)handleBatchFetchScrollingToOffset:(CGPoint)targetOffset { ASDisplayNodeAssert(_batchContext != nil, @"Batch context should exist"); - + if (![self shouldBatchFetch]) { return; } - + if (ASDisplayShouldFetchBatchForContext(_batchContext, [self scrollDirection], self.bounds, self.contentSize, targetOffset, _leadingScreensForBatching)) { [_batchContext beginBatchFetching]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ @@ -695,7 +701,7 @@ static BOOL _isInterceptedSelector(SEL sel) } constrainedSize = ASSizeRangeMake(CGSizeZero, maxSize); } - + UIEdgeInsets sectionInset = UIEdgeInsetsZero; if (_collectionViewLayoutImplementsInsetSection) { sectionInset = [(UICollectionViewFlowLayout *)self.collectionViewLayout sectionInset]; @@ -704,7 +710,7 @@ static BOOL _isInterceptedSelector(SEL sel) if (_asyncDelegateImplementsInsetSection) { sectionInset = [(id)_asyncDelegate collectionView:self layout:self.collectionViewLayout insetForSectionAtIndex:indexPath.section]; } - + if (ASScrollDirectionContainsHorizontalDirection([self scrollableDirections])) { constrainedSize.min.width = MAX(0, constrainedSize.min.width - sectionInset.left - sectionInset.right); //ignore insets for FLT_MAX so FLT_MAX can be compared against @@ -718,7 +724,7 @@ static BOOL _isInterceptedSelector(SEL sel) constrainedSize.max.height = MAX(0, constrainedSize.max.height - sectionInset.top - sectionInset.bottom); } } - + return constrainedSize; } @@ -738,7 +744,7 @@ static BOOL _isInterceptedSelector(SEL sel) - (void)dataControllerLockDataSource { ASDisplayNodeAssert(!self.asyncDataSourceLocked, @"The data source has already been locked"); - + self.asyncDataSourceLocked = YES; if ([_asyncDataSource respondsToSelector:@selector(collectionViewLockDataSource:)]) { [_asyncDataSource collectionViewLockDataSource:self]; @@ -748,7 +754,7 @@ static BOOL _isInterceptedSelector(SEL sel) - (void)dataControllerUnlockDataSource { ASDisplayNodeAssert(self.asyncDataSourceLocked, @"The data source has already been unlocked"); - + self.asyncDataSourceLocked = NO; if ([_asyncDataSource respondsToSelector:@selector(collectionViewUnlockDataSource:)]) { [_asyncDataSource collectionViewUnlockDataSource:self]; @@ -817,7 +823,7 @@ static BOOL _isInterceptedSelector(SEL sel) - (void)rangeController:(ASRangeController *)rangeController didEndUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion { ASDisplayNodeAssertMainThread(); - + if (!self.asyncDataSource || _superIsPendingDataLoad) { if (completion) { completion(NO); @@ -832,7 +838,7 @@ static BOOL _isInterceptedSelector(SEL sel) } } completion:completion]; }); - + [_batchUpdateBlocks removeAllObjects]; _performingBatchUpdates = NO; } @@ -840,11 +846,11 @@ static BOOL _isInterceptedSelector(SEL sel) - (void)rangeController:(ASRangeController *)rangeController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodeAssertMainThread(); - + if (!self.asyncDataSource || _superIsPendingDataLoad) { return; // if the asyncDataSource has become invalid while we are processing, ignore this request to avoid crashes } - + if (_performingBatchUpdates) { [_batchUpdateBlocks addObject:^{ [super insertItemsAtIndexPaths:indexPaths]; @@ -859,11 +865,11 @@ static BOOL _isInterceptedSelector(SEL sel) - (void)rangeController:(ASRangeController *)rangeController didDeleteNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodeAssertMainThread(); - + if (!self.asyncDataSource || _superIsPendingDataLoad) { return; // if the asyncDataSource has become invalid while we are processing, ignore this request to avoid crashes } - + if (_performingBatchUpdates) { [_batchUpdateBlocks addObject:^{ [super deleteItemsAtIndexPaths:indexPaths]; @@ -878,11 +884,11 @@ static BOOL _isInterceptedSelector(SEL sel) - (void)rangeController:(ASRangeController *)rangeController didInsertSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodeAssertMainThread(); - + if (!self.asyncDataSource || _superIsPendingDataLoad) { return; // if the asyncDataSource has become invalid while we are processing, ignore this request to avoid crashes } - + if (_performingBatchUpdates) { [_batchUpdateBlocks addObject:^{ [super insertSections:indexSet]; @@ -897,11 +903,11 @@ static BOOL _isInterceptedSelector(SEL sel) - (void)rangeController:(ASRangeController *)rangeController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodeAssertMainThread(); - + if (!self.asyncDataSource || _superIsPendingDataLoad) { return; // if the asyncDataSource has become invalid while we are processing, ignore this request to avoid crashes } - + if (_performingBatchUpdates) { [_batchUpdateBlocks addObject:^{ [super deleteSections:indexSet]; @@ -918,11 +924,11 @@ static BOOL _isInterceptedSelector(SEL sel) - (void)nodeDidRelayout:(ASCellNode *)node sizeChanged:(BOOL)sizeChanged { ASDisplayNodeAssertMainThread(); - + if (!sizeChanged || _queuedNodeSizeUpdate) { return; } - + _queuedNodeSizeUpdate = YES; [self performSelector:@selector(requeryNodeSizes) withObject:nil @@ -934,7 +940,7 @@ static BOOL _isInterceptedSelector(SEL sel) - (void)requeryNodeSizes { _queuedNodeSizeUpdate = NO; - + [super performBatchUpdates:^{} completion:nil]; } @@ -944,7 +950,7 @@ static BOOL _isInterceptedSelector(SEL sel) { for (NSArray *section in [_dataController completedNodes]) { for (ASDisplayNode *node in section) { - [node recursivelyClearContents]; + [node exitInterfaceState:ASInterfaceStateDisplay]; } } } @@ -953,7 +959,7 @@ static BOOL _isInterceptedSelector(SEL sel) { for (NSArray *section in [_dataController completedNodes]) { for (ASDisplayNode *node in section) { - [node recursivelyClearFetchedData]; + [node exitInterfaceState:ASInterfaceStateFetchData]; } } } diff --git a/AsyncDisplayKit/ASDisplayNode+Subclasses.h b/AsyncDisplayKit/ASDisplayNode+Subclasses.h index b0bb3b0e..108dbdd3 100644 --- a/AsyncDisplayKit/ASDisplayNode+Subclasses.h +++ b/AsyncDisplayKit/ASDisplayNode+Subclasses.h @@ -37,35 +37,8 @@ @interface ASDisplayNode (Subclassing) - -/** @name View Configuration */ - - -/** - * @return The view class to use when creating a new display node instance. Defaults to _ASDisplayView. - */ -+ (Class)viewClass; - - /** @name Properties */ - -/** - * @abstract The scale factor to apply to the rendering. - * - * @discussion Use setNeedsDisplayAtScale: to set a value and then after display, the display node will set the layer's - * contentsScale. This is to prevent jumps when re-rasterizing at a different contentsScale. - * Read this property if you need to know the future contentsScale of your layer, eg in drawParameters. - * - * @see setNeedsDisplayAtScale: - */ -@property (nonatomic, assign, readonly) CGFloat contentsScaleForDisplay; - -/** - * @abstract Whether the view or layer of this display node is currently in a window - */ -@property (nonatomic, readonly, assign, getter=isInHierarchy) BOOL inHierarchy; - /** * @abstract Return the calculated layout. * @@ -190,10 +163,9 @@ * * @note Called on the display queue and/or main queue (MUST BE THREAD SAFE) */ -+ (void)drawRect:(CGRect)bounds - withParameters:(id)parameters - isCancelled:(asdisplaynode_iscancelled_block_t)isCancelledBlock - isRasterizing:(BOOL)isRasterizing; ++ (void)drawRect:(CGRect)bounds withParameters:(id)parameters + isCancelled:(asdisplaynode_iscancelled_block_t)isCancelledBlock + isRasterizing:(BOOL)isRasterizing; /** * @summary Delegate override to provide new layer contents as a UIImage. @@ -236,6 +208,33 @@ */ - (void)displayDidFinish ASDISPLAYNODE_REQUIRES_SUPER; +/** @name Observing node-related changes */ + +/** + * @abstract Called whenever any bit in the ASInterfaceState bitfield is changed. + * + * @discussion Subclasses may use this to monitor when they become visible, should free cached data, and much more. + * @see ASInterfaceState + */ +- (void)interfaceStateDidChange:(ASInterfaceState)newState fromState:(ASInterfaceState)oldState; + +- (void)visibilityDidChange:(BOOL)isVisible; + +/** + * Called just before the view is added to a window. + */ +- (void)willEnterHierarchy ASDISPLAYNODE_REQUIRES_SUPER; + +/** + * Called after the view is removed from the window. + */ +- (void)didExitHierarchy ASDISPLAYNODE_REQUIRES_SUPER; + +/** + * @abstract Whether the view or layer of this display node is currently in a window + */ +@property (nonatomic, readonly, assign, getter=isInHierarchy) BOOL inHierarchy; + /** * @abstract Indicates that the node should fetch any external data, such as images. * @@ -245,6 +244,23 @@ */ - (void)fetchData ASDISPLAYNODE_REQUIRES_SUPER; +/** + * Provides an opportunity to clear any fetched data (e.g. remote / network or database-queried) on the current node. + * + * @discussion This will not clear data recursively for all subnodes. Either call -recursivelyClearFetchedData or + * selectively clear fetched data. + */ +- (void)clearFetchedData ASDISPLAYNODE_REQUIRES_SUPER; + +/** + * Provides an opportunity to clear backing store and other memory-intensive intermediates, such as text layout managers + * on the current node. + * + * @discussion Called by -recursivelyClearContents. Base class implements self.contents = nil, clearing any backing + * store, for asynchronous regeneration when needed. + */ +- (void)clearContents ASDISPLAYNODE_REQUIRES_SUPER; + /** * @abstract Indicates that the receiver is about to display its subnodes. This method is not called if there are no * subnodes present. @@ -267,7 +283,6 @@ */ - (void)subnodeDisplayDidFinish:(ASDisplayNode *)subnode ASDISPLAYNODE_REQUIRES_SUPER; - /** * @abstract Marks the receiver's bounds as needing to be redrawn, with a scale value. * @@ -295,6 +310,17 @@ */ - (void)recursivelySetNeedsDisplayAtScale:(CGFloat)contentsScale; +/** + * @abstract The scale factor to apply to the rendering. + * + * @discussion Use setNeedsDisplayAtScale: to set a value and then after display, the display node will set the layer's + * contentsScale. This is to prevent jumps when re-rasterizing at a different contentsScale. + * Read this property if you need to know the future contentsScale of your layer, eg in drawParameters. + * + * @see setNeedsDisplayAtScale: + */ +@property (nonatomic, assign, readonly) CGFloat contentsScaleForDisplay; + /** @name Touch handling */ @@ -361,38 +387,6 @@ */ - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event; - -/** @name Observing node-related changes */ - - -/** - * Called just before the view is added to a window. - */ -- (void)willEnterHierarchy ASDISPLAYNODE_REQUIRES_SUPER; - -/** - * Called after the view is removed from the window. - */ -- (void)didExitHierarchy ASDISPLAYNODE_REQUIRES_SUPER; - -/** - * Provides an opportunity to clear backing store and other memory-intensive intermediates, such as text layout managers - * on the current node. - * - * @discussion Called by -recursivelyClearContents. Base class implements self.contents = nil, clearing any backing - * store, for asynchronous regeneration when needed. - */ -- (void)clearContents ASDISPLAYNODE_REQUIRES_SUPER; - -/** - * Provides an opportunity to clear any fetched data (e.g. remote / network or database-queried) on the current node. - * - * @discussion This will not clear data recursively for all subnodes. Either call -recursivelyClearFetchedData or - * selectively clear fetched data. - */ -- (void)clearFetchedData ASDISPLAYNODE_REQUIRES_SUPER; - - /** @name Placeholders */ /** @@ -412,6 +406,7 @@ */ - (UIImage *)placeholderImage; + /** @name Description */ /** diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 2d92c188..5fdcb4f7 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -1722,6 +1722,10 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) [self clearFetchedData]; } +- (void)visibilityDidChange:(BOOL)isVisible +{ +} + /** * We currently only set interface state on nodes in table/collection views. For other nodes, if they are * in the hierarchy we enable all ASInterfaceState types with `ASInterfaceStateInHierarchy`, otherwise `None`. @@ -1776,11 +1780,17 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) // Entered or exited data loading state. if ((newState & ASInterfaceStateVisible) != (oldState & ASInterfaceStateVisible)) { if (newState & ASInterfaceStateVisible) { - // Consider providing a -didBecomeVisible. + [self visibilityDidChange:YES]; } else { - // Consider providing a -didBecomeInvisible. + [self visibilityDidChange:NO]; } } + + [self interfaceStateDidChange:newState fromState:oldState]; +} + +- (void)interfaceStateDidChange:(ASInterfaceState)newState fromState:(ASInterfaceState)oldState +{ } - (void)enterInterfaceState:(ASInterfaceState)interfaceState diff --git a/AsyncDisplayKit/ASViewController.h b/AsyncDisplayKit/ASViewController.h index 281a5d0e..7ef1fdf7 100644 --- a/AsyncDisplayKit/ASViewController.h +++ b/AsyncDisplayKit/ASViewController.h @@ -11,14 +11,23 @@ @interface ASViewController : UIViewController +- (instancetype)initWithNode:(ASDisplayNode *)node NS_DESIGNATED_INITIALIZER; + @property (nonatomic, strong, readonly) ASDisplayNode *node; +/** + * @abstract Passthrough property to the the .interfaceState of the node. + * @return The current ASInterfaceState of the node, indicating whether it is visible and other situational properties. + * @see ASInterfaceState + */ +@property (nonatomic, readonly) ASInterfaceState interfaceState; + + // AsyncDisplayKit 2.0 BETA: This property is still being tested, but it allows // blocking as a view controller becomes visible to ensure no placeholders flash onscreen. // Refer to examples/SynchronousConcurrency, AsyncViewController.m @property (nonatomic, assign) BOOL neverShowPlaceholders; -- (instancetype)initWithNode:(ASDisplayNode *)node; /** * The constrained size used to measure the backing node. diff --git a/AsyncDisplayKit/ASViewController.m b/AsyncDisplayKit/ASViewController.m index ab2c6741..3b22a929 100644 --- a/AsyncDisplayKit/ASViewController.m +++ b/AsyncDisplayKit/ASViewController.m @@ -65,4 +65,9 @@ return ASSizeRangeMake(viewSize, viewSize); } +- (ASInterfaceState)interfaceState +{ + return _node.interfaceState; +} + @end diff --git a/AsyncDisplayKit/Private/ASDisplayNode+FrameworkPrivate.h b/AsyncDisplayKit/Private/ASDisplayNode+FrameworkPrivate.h index 701be894..978032d9 100644 --- a/AsyncDisplayKit/Private/ASDisplayNode+FrameworkPrivate.h +++ b/AsyncDisplayKit/Private/ASDisplayNode+FrameworkPrivate.h @@ -57,6 +57,9 @@ typedef NS_OPTIONS(NSUInteger, ASHierarchyState) ASHierarchyState _hierarchyState; } +// The view class to use when creating a new display node instance. Defaults to _ASDisplayView. ++ (Class)viewClass; + // These methods are recursive, and either union or remove the provided interfaceState to all sub-elements. - (void)enterInterfaceState:(ASInterfaceState)interfaceState; - (void)exitInterfaceState:(ASInterfaceState)interfaceState; diff --git a/examples/CustomCollectionView/Sample.xcodeproj/project.pbxproj b/examples/CustomCollectionView/Sample.xcodeproj/project.pbxproj index 57ec7f62..88ca8858 100644 --- a/examples/CustomCollectionView/Sample.xcodeproj/project.pbxproj +++ b/examples/CustomCollectionView/Sample.xcodeproj/project.pbxproj @@ -130,7 +130,6 @@ AC3C4A5B1A11F47200143C57 /* Frameworks */, AC3C4A5C1A11F47200143C57 /* Resources */, A6902C454C7661D0D277AC62 /* Copy Pods Resources */, - EC37EEC9933F5786936BFE7C /* Embed Pods Frameworks */, ); buildRules = ( ); @@ -201,21 +200,6 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; showEnvVarsInLog = 0; }; - EC37EEC9933F5786936BFE7C /* 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; - }; F868CFBB21824CC9521B6588 /* Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; From ff4f2bb270b73f865b2585b30e5a18da156ae3b5 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Tue, 22 Dec 2015 22:19:53 -0800 Subject: [PATCH 40/60] Tweak ASCollectionViewFlowLayoutInspector.h file to make it Public as intended. --- AsyncDisplayKit.xcodeproj/project.pbxproj | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 2e0296d3..f0aee074 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -128,7 +128,7 @@ 242995D31B29743C00090100 /* ASBasicImageDownloaderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 242995D21B29743C00090100 /* ASBasicImageDownloaderTests.m */; }; 251B8EF71BBB3D690087C538 /* ASCollectionDataController.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF21BBB3D690087C538 /* ASCollectionDataController.h */; }; 251B8EF81BBB3D690087C538 /* ASCollectionDataController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 251B8EF31BBB3D690087C538 /* ASCollectionDataController.mm */; }; - 251B8EF91BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF41BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.h */; }; + 251B8EF91BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF41BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.h */; settings = {ATTRIBUTES = (Public, ); }; }; 251B8EFA1BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.m in Sources */ = {isa = PBXBuildFile; fileRef = 251B8EF51BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.m */; }; 251B8EFB1BBB3D690087C538 /* ASDataController+Subclasses.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF61BBB3D690087C538 /* ASDataController+Subclasses.h */; }; 2538B6F31BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2538B6F21BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.m */; }; @@ -458,6 +458,7 @@ D785F6621A74327E00291744 /* ASScrollNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D785F6601A74327E00291744 /* ASScrollNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; D785F6631A74327E00291744 /* ASScrollNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D785F6611A74327E00291744 /* ASScrollNode.m */; }; DB7121BCD50849C498C886FB /* libPods-AsyncDisplayKitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */; }; + DE4A31861C2A747B000D4262 /* ASCollectionViewFlowLayoutInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF41BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.h */; settings = {ATTRIBUTES = (Public, ); }; }; DE6EA3221C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */; }; DE6EA3231C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */; }; DECBD6E71BE56E1900CF4905 /* ASButtonNode.h in Headers */ = {isa = PBXBuildFile; fileRef = DECBD6E51BE56E1900CF4905 /* ASButtonNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1451,6 +1452,7 @@ B35062551B010EFD0018CF92 /* ASSentinel.h in Headers */, 9C8221961BA237B80037F19A /* ASStackBaselinePositionedLayout.h in Headers */, 9C49C3701B853961000B0DD5 /* ASStackLayoutable.h in Headers */, + DE4A31861C2A747B000D4262 /* ASCollectionViewFlowLayoutInspector.h in Headers */, 34EFC7701B701CFA00AD841F /* ASStackLayoutDefines.h in Headers */, 254C6B7B1BF94DF4003EC431 /* ASTextKitRenderer+Positioning.h in Headers */, CC7FD9E21BB603FF005CCB2B /* ASPhotosFrameworkImageRequest.h in Headers */, From 9944305cfdccda37cb3a984561507981e89d349e Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Tue, 22 Dec 2015 23:36:29 -0800 Subject: [PATCH 41/60] Fix tests to avoid newly deprecated ASCollectionView init variant with asyncDataFetching argument. --- AsyncDisplayKit.xcodeproj/project.pbxproj | 16 ----------- AsyncDisplayKit/ASCollectionNode.h | 3 +- AsyncDisplayKit/ASCollectionNode.m | 9 ++++-- AsyncDisplayKit/ASCollectionView.h | 1 + AsyncDisplayKit/ASCollectionView.mm | 6 ++-- ...ASCollectionViewFlowLayoutInspectorTests.m | 28 +++++++++---------- 6 files changed, 26 insertions(+), 37 deletions(-) diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index f0aee074..2e2e1122 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -1525,7 +1525,6 @@ 058D09B9195D04C000B7D73C /* Frameworks */, 058D09BA195D04C000B7D73C /* Resources */, 3B9D88CDF51B429C8409E4B6 /* Copy Pods Resources */, - 1B86F48711505F91D5FEF571 /* Embed Pods Frameworks */, ); buildRules = ( ); @@ -1625,21 +1624,6 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 1B86F48711505F91D5FEF571 /* 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-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; 2E61B6A0DB0F436A9DDBE86F /* Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; diff --git a/AsyncDisplayKit/ASCollectionNode.h b/AsyncDisplayKit/ASCollectionNode.h index 4f860cb6..8109c897 100644 --- a/AsyncDisplayKit/ASCollectionNode.h +++ b/AsyncDisplayKit/ASCollectionNode.h @@ -14,7 +14,8 @@ */ @interface ASCollectionNode : ASDisplayNode -- (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout; +- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout; @property (nonatomic, readonly) ASCollectionView *view; diff --git a/AsyncDisplayKit/ASCollectionNode.m b/AsyncDisplayKit/ASCollectionNode.m index eb0ddd30..8c74d62c 100644 --- a/AsyncDisplayKit/ASCollectionNode.m +++ b/AsyncDisplayKit/ASCollectionNode.m @@ -10,7 +10,7 @@ #import "ASDisplayNode+Subclasses.h" @interface ASCollectionView (Internal) -- (ASCollectionView *)_initWithCollectionViewLayout:(UICollectionViewLayout *)layout; +- (instancetype)_initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout; @end @implementation ASCollectionNode @@ -24,7 +24,12 @@ - (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout { - if (self = [super initWithViewBlock:^UIView *{ return [[ASCollectionView alloc] _initWithCollectionViewLayout:layout]; }]) { + return [self initWithFrame:CGRectZero collectionViewLayout:layout]; +} + +- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout +{ + if (self = [super initWithViewBlock:^UIView *{ return [[ASCollectionView alloc] _initWithFrame:frame collectionViewLayout:layout]; }]) { return self; } return nil; diff --git a/AsyncDisplayKit/ASCollectionView.h b/AsyncDisplayKit/ASCollectionView.h index 8d715e3e..5d93fdcd 100644 --- a/AsyncDisplayKit/ASCollectionView.h +++ b/AsyncDisplayKit/ASCollectionView.h @@ -33,6 +33,7 @@ * @param layout The layout object to use for organizing items. The collection view stores a strong reference to the specified object. Must not be nil. */ - (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout; +- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout; @property (nonatomic, weak) id asyncDataSource; @property (nonatomic, weak) id asyncDelegate; // must not be nil diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index 0aeefb27..5d3d051b 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -193,10 +193,8 @@ static BOOL _isInterceptedSelector(SEL sel) - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout { -// ASCollectionNode *collectionNode = [[ASCollectionNode alloc] initWithCollectionViewLayout:layout]; -// collectionNode.frame = frame; -// return collectionNode.view; - return [self _initWithFrame:frame collectionViewLayout:layout]; + ASCollectionNode *collectionNode = [[ASCollectionNode alloc] initWithFrame:frame collectionViewLayout:layout]; + return collectionNode.view; } // FIXME: This method is deprecated and will probably be removed in or shortly after 2.0. diff --git a/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m b/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m index 1230807f..a9c5614e 100644 --- a/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m +++ b/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m @@ -100,7 +100,7 @@ layout.scrollDirection = UICollectionViewScrollDirectionVertical; CGRect rect = CGRectMake(0, 0, 100.0, 100.0); - ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout asyncDataFetching:NO]; + ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout]; collectionView.asyncDataSource = dataSource; collectionView.asyncDelegate = delegate; @@ -122,7 +122,7 @@ layout.scrollDirection = UICollectionViewScrollDirectionVertical; CGRect rect = CGRectMake(0, 0, 100.0, 100.0); - ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout asyncDataFetching:NO]; + ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout]; collectionView.asyncDataSource = dataSource; collectionView.asyncDelegate = delegate; @@ -146,7 +146,7 @@ layout.headerReferenceSize = CGSizeMake(125.0, 125.0); CGRect rect = CGRectMake(0, 0, 100.0, 100.0); - ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout asyncDataFetching:NO]; + ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout]; collectionView.asyncDataSource = dataSource; ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; @@ -167,7 +167,7 @@ layout.footerReferenceSize = CGSizeMake(125.0, 125.0); CGRect rect = CGRectMake(0, 0, 100.0, 100.0); - ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout asyncDataFetching:NO]; + ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout]; collectionView.asyncDataSource = dataSource; ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; @@ -190,7 +190,7 @@ layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; CGRect rect = CGRectMake(0, 0, 100.0, 100.0); - ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout asyncDataFetching:NO]; + ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout]; collectionView.asyncDataSource = dataSource; collectionView.asyncDelegate = delegate; @@ -212,7 +212,7 @@ layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; CGRect rect = CGRectMake(0, 0, 100.0, 100.0); - ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout asyncDataFetching:NO]; + ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout]; collectionView.asyncDataSource = dataSource; collectionView.asyncDelegate = delegate; @@ -236,7 +236,7 @@ layout.headerReferenceSize = CGSizeMake(125.0, 125.0); CGRect rect = CGRectMake(0, 0, 100.0, 100.0); - ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout asyncDataFetching:NO]; + ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout]; collectionView.asyncDataSource = dataSource; ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; @@ -257,7 +257,7 @@ layout.footerReferenceSize = CGSizeMake(125.0, 125.0); CGRect rect = CGRectMake(0, 0, 100.0, 100.0); - ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout asyncDataFetching:NO]; + ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout]; collectionView.asyncDataSource = dataSource; ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; @@ -274,7 +274,7 @@ InspectorTestDataSource *dataSource = [[InspectorTestDataSource alloc] init]; HeaderReferenceSizeTestDelegate *delegate = [[HeaderReferenceSizeTestDelegate alloc] init]; UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; - ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout asyncDataFetching:NO]; + ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; collectionView.asyncDataSource = dataSource; collectionView.asyncDelegate = delegate; ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; @@ -291,7 +291,7 @@ - (void)testThatItRespondsWithTheDefaultNumberOfSections { UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; - ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout asyncDataFetching:NO]; + ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; NSUInteger sections = [inspector collectionView:collectionView numberOfSectionsForSupplementaryNodeOfKind:UICollectionElementKindSectionHeader]; XCTAssert(sections == 1, @"should return 1 by default"); @@ -304,7 +304,7 @@ { InspectorTestDataSource *dataSource = [[InspectorTestDataSource alloc] init]; UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; - ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout asyncDataFetching:NO]; + ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; collectionView.asyncDataSource = dataSource; ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; NSUInteger sections = [inspector collectionView:collectionView numberOfSectionsForSupplementaryNodeOfKind:UICollectionElementKindSectionHeader]; @@ -321,7 +321,7 @@ InspectorTestDataSource *dataSource = [[InspectorTestDataSource alloc] init]; HeaderReferenceSizeTestDelegate *delegate = [[HeaderReferenceSizeTestDelegate alloc] init]; UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; - ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout asyncDataFetching:NO]; + ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; collectionView.asyncDataSource = dataSource; collectionView.asyncDelegate = delegate; ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; @@ -338,7 +338,7 @@ HeaderReferenceSizeTestDelegate *delegate = [[HeaderReferenceSizeTestDelegate alloc] init]; UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; layout.footerReferenceSize = CGSizeMake(125.0, 125.0); - ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout asyncDataFetching:NO]; + ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; collectionView.asyncDataSource = dataSource; collectionView.asyncDelegate = delegate; ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; @@ -354,7 +354,7 @@ InspectorTestDataSource *dataSource = [[InspectorTestDataSource alloc] init]; HeaderReferenceSizeTestDelegate *delegate = [[HeaderReferenceSizeTestDelegate alloc] init]; UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; - ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout asyncDataFetching:NO]; + ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; collectionView.asyncDataSource = dataSource; collectionView.asyncDelegate = delegate; ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; From e35697d162f667047ae6b47835ac9e493262782a Mon Sep 17 00:00:00 2001 From: Aaron Schubert Date: Wed, 23 Dec 2015 10:19:05 +0000 Subject: [PATCH 42/60] Greatly improve the internal logic of ASMapNode. Also fixes bug #971 --- AsyncDisplayKit/ASMapNode.h | 4 +- AsyncDisplayKit/ASMapNode.mm | 119 +++++++++++++++++++---------------- 2 files changed, 66 insertions(+), 57 deletions(-) diff --git a/AsyncDisplayKit/ASMapNode.h b/AsyncDisplayKit/ASMapNode.h index acabf841..bd2d23ad 100644 --- a/AsyncDisplayKit/ASMapNode.h +++ b/AsyncDisplayKit/ASMapNode.h @@ -12,7 +12,7 @@ @interface ASMapNode : ASImageNode /** - The current region of ASMapNode. This can be set at any time and ASMapNode will animate the change. + The current region of ASMapNode. This can be set at any time and ASMapNode will animate the change. This property may be set from a background thread before the node is loaded, and will automatically be applied to define the region of the static snapshot (if .liveMap = NO) or the internal MKMapView (otherwise). */ @property (nonatomic, assign) MKCoordinateRegion region; @@ -22,7 +22,7 @@ @property (nonatomic, readonly) MKMapView *mapView; /** - Set this to YES to turn the snapshot into an interactive MKMapView and vice versa. Defaults to NO. + Set this to YES to turn the snapshot into an interactive MKMapView and vice versa. Defaults to NO. This property may be set on a background thread before the node is loaded, and will automatically be actioned, once the node is loaded. */ @property (nonatomic, assign, getter=isLiveMap) BOOL liveMap; diff --git a/AsyncDisplayKit/ASMapNode.mm b/AsyncDisplayKit/ASMapNode.mm index 80a76fc8..480360a1 100644 --- a/AsyncDisplayKit/ASMapNode.mm +++ b/AsyncDisplayKit/ASMapNode.mm @@ -26,6 +26,7 @@ @synthesize needsMapReloadOnBoundsChange = _needsMapReloadOnBoundsChange; @synthesize mapDelegate = _mapDelegate; @synthesize region = _region; +@synthesize liveMap = _liveMap; #pragma mark - Lifecycle - (instancetype)init @@ -37,9 +38,11 @@ self.clipsToBounds = YES; _needsMapReloadOnBoundsChange = YES; - + _liveMap = NO; _centerCoordinateOfMap = kCLLocationCoordinate2DInvalid; - _region = MKCoordinateRegionMake(CLLocationCoordinate2DMake(43.432858, 13.183671), MKCoordinateSpanMake(0.2, 0.2)); + + //Default world-scale view + _region = MKCoordinateRegionForMapRect(MKMapRectWorld); _options = [[MKMapSnapshotOptions alloc] init]; _options.region = _region; @@ -50,26 +53,31 @@ - (void)didLoad { [super didLoad]; - if ([self wasLiveMapPreviously]) { + if (self.isLiveMap) { self.userInteractionEnabled = YES; [self addLiveMap]; } } +- (void)setLayerBacked:(BOOL)layerBacked +{ + ASDisplayNodeAssert(!self.isLiveMap, @"ASMapNode can not be layer backed whilst .liveMap = YES, set .liveMap = NO to use layer backing."); + [super setLayerBacked:layerBacked]; +} + - (void)fetchData { [super fetchData]; - if ([self wasLiveMapPreviously]) { + if (self.isLiveMap) { [self addLiveMap]; } else { - [self setUpSnapshotter]; [self takeSnapshot]; } } -- (void)clearFetchedData +- (void)clearContents { - [super clearFetchedData]; + [super clearContents]; if (self.isLiveMap) { [self removeLiveMap]; } @@ -79,17 +87,21 @@ - (BOOL)isLiveMap { - return (_mapView != nil); + ASDN::MutexLocker l(_propertyLock); + return _liveMap; } - (void)setLiveMap:(BOOL)liveMap { - liveMap ? [self addLiveMap] : [self removeLiveMap]; -} - -- (BOOL)wasLiveMapPreviously -{ - return CLLocationCoordinate2DIsValid(_centerCoordinateOfMap); + ASDisplayNodeAssert(!self.isLayerBacked, @"ASMapNode can not use the interactive map feature whilst .isLayerBacked = YES, set .layerBacked = NO to use the interactive map feature."); + ASDN::MutexLocker l(_propertyLock); + if (liveMap == _liveMap) { + return; + } + _liveMap = liveMap; + if (self.nodeLoaded) { + liveMap ? [self addLiveMap] : [self removeLiveMap]; + } } - (BOOL)needsMapReloadOnBoundsChange @@ -127,63 +139,62 @@ - (void)takeSnapshot { - if (!_snapshotter.isLoading) { - [_snapshotter startWithCompletionHandler:^(MKMapSnapshot *snapshot, NSError *error) { - if (!error) { - UIImage *image = snapshot.image; - CGRect finalImageRect = CGRectMake(0, 0, image.size.width, image.size.height); - - UIGraphicsBeginImageContextWithOptions(image.size, YES, image.scale); - [image drawAtPoint:CGPointMake(0, 0)]; - - if (_annotations.count > 0 ) { - // Get a standard annotation view pin. Future implementations should use a custom annotation image property. - MKAnnotationView *pin = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:@""]; - UIImage *pinImage = pin.image; - for (idannotation in _annotations) + if (!_snapshotter) { + [self setUpSnapshotter]; + } + [_snapshotter cancel]; + [_snapshotter startWithCompletionHandler:^(MKMapSnapshot *snapshot, NSError *error) { + if (!error) { + UIImage *image = snapshot.image; + CGRect finalImageRect = CGRectMake(0, 0, image.size.width, image.size.height); + + UIGraphicsBeginImageContextWithOptions(image.size, YES, image.scale); + [image drawAtPoint:CGPointMake(0, 0)]; + + if (_annotations.count > 0 ) { + // Get a standard annotation view pin. Future implementations should use a custom annotation image property. + MKAnnotationView *pin = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:@""]; + UIImage *pinImage = pin.image; + for (idannotation in _annotations) + { + CGPoint point = [snapshot pointForCoordinate:annotation.coordinate]; + if (CGRectContainsPoint(finalImageRect, point)) { - CGPoint point = [snapshot pointForCoordinate:annotation.coordinate]; - if (CGRectContainsPoint(finalImageRect, point)) - { - CGPoint pinCenterOffset = pin.centerOffset; - point.x -= pin.bounds.size.width / 2.0; - point.y -= pin.bounds.size.height / 2.0; - point.x += pinCenterOffset.x; - point.y += pinCenterOffset.y; - [pinImage drawAtPoint:point]; - } + CGPoint pinCenterOffset = pin.centerOffset; + point.x -= pin.bounds.size.width / 2.0; + point.y -= pin.bounds.size.height / 2.0; + point.x += pinCenterOffset.x; + point.y += pinCenterOffset.y; + [pinImage drawAtPoint:point]; } } - - UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - self.image = finalImage; } - }]; - } + + UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + self.image = finalImage; + } + }]; } - (void)setUpSnapshotter { - 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]; - } + 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]; } - (void)resetSnapshotter { - if (!_snapshotter.isLoading) { - _snapshotter = [[MKMapSnapshotter alloc] initWithOptions:_options]; - } + [_snapshotter cancel]; + _snapshotter = [[MKMapSnapshotter alloc] initWithOptions:_options]; } #pragma mark - Actions - (void)addLiveMap { ASDisplayNodeAssertMainThread(); - if (!self.isLiveMap) { + if (!_mapView) { __weak ASMapNode *weakSelf = self; _mapView = [[MKMapView alloc] initWithFrame:CGRectZero]; _mapView.delegate = weakSelf.mapDelegate; @@ -194,8 +205,6 @@ if (CLLocationCoordinate2DIsValid(_centerCoordinateOfMap)) { [_mapView setCenterCoordinate:_centerCoordinateOfMap]; - } else { - _centerCoordinateOfMap = _options.region.center; } } } From 38d9ceb230abc1be1de9db5355d08d2cfc1e6556 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Wed, 23 Dec 2015 12:52:38 -0800 Subject: [PATCH 43/60] Fix corrupted project file from merge. --- AsyncDisplayKit.xcodeproj/project.pbxproj | 23 ++----------------- AsyncDisplayKit/ASViewController.m | 10 ++++++++ .../ASBasicImageDownloaderTests.m | 7 +++--- 3 files changed, 16 insertions(+), 24 deletions(-) diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index ce1300c9..a044ff48 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -458,7 +458,7 @@ D785F6621A74327E00291744 /* ASScrollNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D785F6601A74327E00291744 /* ASScrollNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; D785F6631A74327E00291744 /* ASScrollNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D785F6611A74327E00291744 /* ASScrollNode.m */; }; DB7121BCD50849C498C886FB /* libPods-AsyncDisplayKitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */; }; - DE4A31861C2A747B000D4262 /* ASCollectionViewFlowLayoutInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF41BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DE040EF91C2B40AC004692FF /* ASCollectionViewFlowLayoutInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF41BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.h */; settings = {ATTRIBUTES = (Public, ); }; }; DE6EA3221C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */; }; DE6EA3231C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */; }; DECBD6E71BE56E1900CF4905 /* ASButtonNode.h in Headers */ = {isa = PBXBuildFile; fileRef = DECBD6E51BE56E1900CF4905 /* ASButtonNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1452,7 +1452,7 @@ B35062551B010EFD0018CF92 /* ASSentinel.h in Headers */, 9C8221961BA237B80037F19A /* ASStackBaselinePositionedLayout.h in Headers */, 9C49C3701B853961000B0DD5 /* ASStackLayoutable.h in Headers */, - DE4A31861C2A747B000D4262 /* ASCollectionViewFlowLayoutInspector.h in Headers */, + DE040EF91C2B40AC004692FF /* ASCollectionViewFlowLayoutInspector.h in Headers */, 34EFC7701B701CFA00AD841F /* ASStackLayoutDefines.h in Headers */, 254C6B7B1BF94DF4003EC431 /* ASTextKitRenderer+Positioning.h in Headers */, CC7FD9E21BB603FF005CCB2B /* ASPhotosFrameworkImageRequest.h in Headers */, @@ -1525,10 +1525,6 @@ 058D09B9195D04C000B7D73C /* Frameworks */, 058D09BA195D04C000B7D73C /* Resources */, 3B9D88CDF51B429C8409E4B6 /* Copy Pods Resources */, -<<<<<<< HEAD -======= - 5ADEA7587189397768F2B36C /* Embed Pods Frameworks */, ->>>>>>> master ); buildRules = ( ); @@ -1658,21 +1654,6 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 5ADEA7587189397768F2B36C /* 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-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/AsyncDisplayKit/ASViewController.m b/AsyncDisplayKit/ASViewController.m index 3b22a929..519ac4b3 100644 --- a/AsyncDisplayKit/ASViewController.m +++ b/AsyncDisplayKit/ASViewController.m @@ -16,6 +16,16 @@ BOOL _ensureDisplayed; } +- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + return [self initWithNode:nil]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder +{ + return [self initWithNode:nil]; +} + - (instancetype)initWithNode:(ASDisplayNode *)node { if (!(self = [super initWithNibName:nil bundle:nil])) { diff --git a/AsyncDisplayKitTests/ASBasicImageDownloaderTests.m b/AsyncDisplayKitTests/ASBasicImageDownloaderTests.m index e0d7e3c9..11271b23 100644 --- a/AsyncDisplayKitTests/ASBasicImageDownloaderTests.m +++ b/AsyncDisplayKitTests/ASBasicImageDownloaderTests.m @@ -1,5 +1,5 @@ // -// ASBasicImageDownloaderTests.m +// ASZBasicImageDownloaderTests.m // AsyncDisplayKit // // Created by Victor Mayorov on 10/06/15. @@ -10,11 +10,12 @@ #import -@interface ASBasicImageDownloaderTests : XCTestCase +// Z in the name to delay running until after the test instance is operating normally. +@interface ASZBasicImageDownloaderTests : XCTestCase @end -@implementation ASBasicImageDownloaderTests +@implementation ASZBasicImageDownloaderTests - (void)testAsynchronouslyDownloadTheSameURLTwice { From 928c440b4c8a5f7e8ff8d5a924931bfdd0b2a930 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Wed, 23 Dec 2015 16:38:33 -0800 Subject: [PATCH 44/60] Several small optimizations, especially to _ASPendingState and other hot paths. --- AsyncDisplayKit/ASControlNode.m | 5 ++- AsyncDisplayKit/ASDisplayNode.mm | 8 ++-- AsyncDisplayKit/ASPagerNode.m | 11 +++--- AsyncDisplayKit/ASTextNode.mm | 4 +- .../Private/ASDisplayNode+AsyncDisplay.mm | 6 +-- .../Private/ASDisplayNodeInternal.h | 3 ++ AsyncDisplayKit/Private/_ASPendingState.m | 39 ++++++++++++------- 7 files changed, 48 insertions(+), 28 deletions(-) diff --git a/AsyncDisplayKit/ASControlNode.m b/AsyncDisplayKit/ASControlNode.m index 8a5d89ed..8278b9a2 100644 --- a/AsyncDisplayKit/ASControlNode.m +++ b/AsyncDisplayKit/ASControlNode.m @@ -76,7 +76,6 @@ void _ASEnumerateControlEventsIncludedInMaskWithBlock(ASControlNodeEvent mask, v if (!(self = [super init])) return nil; - _controlEventDispatchTable = [[NSMutableDictionary alloc] initWithCapacity:kASControlNodeEventDispatchTableInitialCapacity]; // enough to handle common types without re-hashing the dictionary when adding entries. _enabled = YES; // As we have no targets yet, we start off with user interaction off. When a target is added, it'll get turned back on. @@ -214,6 +213,10 @@ void _ASEnumerateControlEventsIncludedInMaskWithBlock(ASControlNodeEvent mask, v // Convert nil to [NSNull null] so that it can be used as a key for NSMapTable. if (!target) target = [NSNull null]; + + if (!_controlEventDispatchTable) { + _controlEventDispatchTable = [[NSMutableDictionary alloc] initWithCapacity:kASControlNodeEventDispatchTableInitialCapacity]; // enough to handle common types without re-hashing the dictionary when adding entries. + } // Enumerate the events in the mask, adding the target-action pair for each control event included in controlEventMask _ASEnumerateControlEventsIncludedInMaskWithBlock(controlEventMask, ^ diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 5fdcb4f7..5540c7c8 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -1470,9 +1470,9 @@ static NSInteger incrementIfFound(NSInteger i) { } // Helper method to summarize whether or not the node run through the display process -- (BOOL)_implementsDisplay +- (BOOL)__implementsDisplay { - return _flags.implementsDrawRect == YES || _flags.implementsImageDisplay == YES; + return _flags.implementsDrawRect == YES || _flags.implementsImageDisplay == YES || self.shouldRasterizeDescendants; } - (void)_setupPlaceholderLayer @@ -1502,7 +1502,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) // (even a runloop observer at a late call order will not stop the next frame from compositing, showing placeholders). ASDisplayNode *node = [layer asyncdisplaykit_node]; - if (!layer.contents && [node _implementsDisplay]) { + if (!layer.contents && [node __implementsDisplay]) { // For layers that do get displayed here, this immediately kicks off the work on the concurrent -[_ASDisplayLayer displayQueue]. // At the same time, it creates an associated _ASAsyncTransaction, which we can use to block on display completion. See ASDisplayNode+AsyncDisplay.mm. [layer displayIfNeeded]; @@ -2148,7 +2148,7 @@ static void _recursivelySetDisplaySuspended(ASDisplayNode *node, CALayer *layer, self.asyncLayer.displaySuspended = flag; - if ([self _implementsDisplay]) { + if ([self __implementsDisplay]) { if (flag) { [_supernode subnodeDisplayDidFinish:self]; } else { diff --git a/AsyncDisplayKit/ASPagerNode.m b/AsyncDisplayKit/ASPagerNode.m index fef60e2e..eead9a30 100644 --- a/AsyncDisplayKit/ASPagerNode.m +++ b/AsyncDisplayKit/ASPagerNode.m @@ -20,13 +20,14 @@ - (instancetype)init { - _flowLayout = [[UICollectionViewFlowLayout alloc] init]; - _flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; - _flowLayout.minimumInteritemSpacing = 0; - _flowLayout.minimumLineSpacing = 0; + UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init]; + flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; + flowLayout.minimumInteritemSpacing = 0; + flowLayout.minimumLineSpacing = 0; - self = [super initWithCollectionViewLayout:_flowLayout]; + self = [super initWithCollectionViewLayout:flowLayout]; if (self != nil) { + _flowLayout = flowLayout; } return self; } diff --git a/AsyncDisplayKit/ASTextNode.mm b/AsyncDisplayKit/ASTextNode.mm index 56490d18..3eb5c5ba 100644 --- a/AsyncDisplayKit/ASTextNode.mm +++ b/AsyncDisplayKit/ASTextNode.mm @@ -97,6 +97,8 @@ static NSString *ASTextNodeTruncationTokenAttributeName = @"ASTextNodeTruncation #pragma mark - NSObject +static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; + - (instancetype)init { if (self = [super init]) { @@ -120,7 +122,7 @@ static NSString *ASTextNodeTruncationTokenAttributeName = @"ASTextNodeTruncation self.opaque = NO; self.backgroundColor = [UIColor clearColor]; - self.linkAttributeNames = @[ NSLinkAttributeName ]; + self.linkAttributeNames = DefaultLinkAttributeNames; // Accessibility self.isAccessibilityElement = YES; diff --git a/AsyncDisplayKit/Private/ASDisplayNode+AsyncDisplay.mm b/AsyncDisplayKit/Private/ASDisplayNode+AsyncDisplay.mm index 525d1b4b..b0cabb67 100644 --- a/AsyncDisplayKit/Private/ASDisplayNode+AsyncDisplay.mm +++ b/AsyncDisplayKit/Private/ASDisplayNode+AsyncDisplay.mm @@ -175,8 +175,6 @@ static void __ASDisplayLayerDecrementConcurrentDisplayCount(BOOL displayIsAsync, - (asyncdisplaykit_async_transaction_operation_block_t)_displayBlockWithAsynchronous:(BOOL)asynchronous isCancelledBlock:(asdisplaynode_iscancelled_block_t)isCancelledBlock rasterizing:(BOOL)rasterizing { - id nodeClass = [self class]; - asyncdisplaykit_async_transaction_operation_block_t displayBlock = nil; ASDisplayNodeAssert(rasterizing || !(_hierarchyState & ASHierarchyStateRasterized), @"Rasterized descendants should never display unless being drawn into the rasterized container."); @@ -235,7 +233,7 @@ static void __ASDisplayLayerDecrementConcurrentDisplayCount(BOOL displayIsAsync, ASDN_DELAY_FOR_DISPLAY(); - UIImage *result = [nodeClass displayWithParameters:drawParameters isCancelled:isCancelledBlock]; + UIImage *result = [[self class] displayWithParameters:drawParameters isCancelled:isCancelledBlock]; __ASDisplayLayerDecrementConcurrentDisplayCount(asynchronous, rasterizing); return result; }; @@ -265,7 +263,7 @@ static void __ASDisplayLayerDecrementConcurrentDisplayCount(BOOL displayIsAsync, UIGraphicsBeginImageContextWithOptions(bounds.size, opaque, contentsScaleForDisplay); } - [nodeClass drawRect:bounds withParameters:drawParameters isCancelled:isCancelledBlock isRasterizing:rasterizing]; + [[self class] drawRect:bounds withParameters:drawParameters isCancelled:isCancelledBlock isRasterizing:rasterizing]; if (isCancelledBlock()) { if (!rasterizing) { diff --git a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h index e16eb990..c4c9d2ab 100644 --- a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h +++ b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h @@ -144,6 +144,9 @@ typedef NS_OPTIONS(NSUInteger, ASDisplayNodeMethodOverrides) // Call didExitHierarchy if necessary and set inHierarchy = NO if visibility notifications are enabled on all of its parents - (void)__exitHierarchy; +// Helper method to summarize whether or not the node run through the display process +- (BOOL)__implementsDisplay; + // Display the node's view/layer immediately on the current thread, bypassing the background thread rendering. Will be deprecated. - (void)displayImmediately; diff --git a/AsyncDisplayKit/Private/_ASPendingState.m b/AsyncDisplayKit/Private/_ASPendingState.m index a9f70883..8d2c8f76 100644 --- a/AsyncDisplayKit/Private/_ASPendingState.m +++ b/AsyncDisplayKit/Private/_ASPendingState.m @@ -135,19 +135,24 @@ @synthesize borderColor=borderColor; @synthesize asyncdisplaykit_asyncTransactionContainer=asyncTransactionContainer; + +static CGColorRef blackColorRef = NULL; +static UIColor *defaultTintColor = nil; + - (id)init { if (!(self = [super init])) return nil; - // Default UIKit color is an RGB color - static CGColorRef black; + static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ + // Default UIKit color is an RGB color CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - black = CGColorCreate(colorSpace, (CGFloat[]){0,0,0,1} ); - CFRetain(black); + blackColorRef = CGColorCreate(colorSpace, (CGFloat[]){0,0,0,1} ); + CFRetain(blackColorRef); CGColorSpaceRelease(colorSpace); + defaultTintColor = [UIColor colorWithRed:0.0 green:0.478 blue:1.0 alpha:1.0]; }); // Set defaults, these come from the defaults specified in CALayer and UIView @@ -156,7 +161,7 @@ frame = CGRectZero; bounds = CGRectZero; backgroundColor = nil; - tintColor = [UIColor colorWithRed:0.0 green:0.478 blue:1.0 alpha:1.0]; + tintColor = defaultTintColor; contents = nil; isHidden = NO; needsDisplayOnBoundsChange = NO; @@ -172,14 +177,12 @@ transform = CATransform3DIdentity; sublayerTransform = CATransform3DIdentity; userInteractionEnabled = YES; - CFRetain(black); - shadowColor = black; + shadowColor = blackColorRef; shadowOpacity = 0.0; shadowOffset = CGSizeMake(0, -3); shadowRadius = 3; borderWidth = 0; - CFRetain(black); - borderColor = black; + borderColor = blackColorRef; isAccessibilityElement = NO; accessibilityLabel = nil; accessibilityHint = nil; @@ -376,7 +379,9 @@ return; } - CGColorRelease(shadowColor); + if (shadowColor != blackColorRef) { + CGColorRelease(shadowColor); + } shadowColor = color; CGColorRetain(shadowColor); @@ -413,7 +418,9 @@ return; } - CGColorRelease(borderColor); + if (borderColor != blackColorRef) { + CGColorRelease(borderColor); + } borderColor = color; CGColorRetain(borderColor); @@ -1002,8 +1009,14 @@ - (void)dealloc { CGColorRelease(backgroundColor); - CGColorRelease(shadowColor); - CGColorRelease(borderColor); + + if (shadowColor != blackColorRef) { + CGColorRelease(shadowColor); + } + + if (borderColor != blackColorRef) { + CGColorRelease(borderColor); + } } @end From ca57059322e817f31ef84f09a5d1a4e0fa729a65 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Wed, 23 Dec 2015 20:01:52 -0800 Subject: [PATCH 45/60] New ASDelegateProxy class to unify logic for Table & Collection forwarding. Fix dealloc-during-animation crash. --- AsyncDisplayKit.xcodeproj/project.pbxproj | 12 ++ .../contents.xcworkspacedata | 6 + AsyncDisplayKit/ASCollectionView.mm | 141 +++++------------ AsyncDisplayKit/ASTableView.mm | 142 +++++------------- AsyncDisplayKit/Details/ASDelegateProxy.h | 51 +++++++ AsyncDisplayKit/Details/ASDelegateProxy.m | 117 +++++++++++++++ .../ASBasicImageDownloaderTests.m | 19 +-- .../Sample.xcodeproj/project.pbxproj | 22 +-- .../contents.xcworkspacedata | 10 ++ .../ASCollectionView/Sample/AppDelegate.h | 2 + .../ASCollectionView/Sample/AppDelegate.m | 9 +- .../Sample/PresentingViewController.h | 13 ++ .../Sample/PresentingViewController.m | 30 ++++ .../ASCollectionView/Sample/ViewController.m | 41 ++++- 14 files changed, 382 insertions(+), 233 deletions(-) create mode 100644 AsyncDisplayKit/Details/ASDelegateProxy.h create mode 100644 AsyncDisplayKit/Details/ASDelegateProxy.m create mode 100644 examples/ASCollectionView/Sample.xcworkspace/contents.xcworkspacedata create mode 100644 examples/ASCollectionView/Sample/PresentingViewController.h create mode 100644 examples/ASCollectionView/Sample/PresentingViewController.m diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index a044ff48..136a89cb 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -461,6 +461,10 @@ DE040EF91C2B40AC004692FF /* ASCollectionViewFlowLayoutInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF41BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.h */; settings = {ATTRIBUTES = (Public, ); }; }; DE6EA3221C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */; }; DE6EA3231C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */; }; + DEC447B51C2B9DBC00C8CBD1 /* ASDelegateProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = DEC447B31C2B9DBC00C8CBD1 /* ASDelegateProxy.h */; }; + DEC447B61C2B9DBC00C8CBD1 /* ASDelegateProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = DEC447B31C2B9DBC00C8CBD1 /* ASDelegateProxy.h */; }; + DEC447B71C2B9DBC00C8CBD1 /* ASDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = DEC447B41C2B9DBC00C8CBD1 /* ASDelegateProxy.m */; }; + DEC447B81C2B9DBC00C8CBD1 /* ASDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = DEC447B41C2B9DBC00C8CBD1 /* ASDelegateProxy.m */; }; DECBD6E71BE56E1900CF4905 /* ASButtonNode.h in Headers */ = {isa = PBXBuildFile; fileRef = DECBD6E51BE56E1900CF4905 /* ASButtonNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; DECBD6E81BE56E1900CF4905 /* ASButtonNode.h in Headers */ = {isa = PBXBuildFile; fileRef = DECBD6E51BE56E1900CF4905 /* ASButtonNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; DECBD6E91BE56E1900CF4905 /* ASButtonNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = DECBD6E61BE56E1900CF4905 /* ASButtonNode.mm */; }; @@ -754,6 +758,8 @@ D785F6601A74327E00291744 /* ASScrollNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASScrollNode.h; sourceTree = ""; }; D785F6611A74327E00291744 /* ASScrollNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASScrollNode.m; sourceTree = ""; }; DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASDisplayNode+FrameworkPrivate.h"; sourceTree = ""; }; + DEC447B31C2B9DBC00C8CBD1 /* ASDelegateProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDelegateProxy.h; sourceTree = ""; }; + DEC447B41C2B9DBC00C8CBD1 /* ASDelegateProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDelegateProxy.m; sourceTree = ""; }; DECBD6E51BE56E1900CF4905 /* ASButtonNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASButtonNode.h; sourceTree = ""; }; DECBD6E61BE56E1900CF4905 /* ASButtonNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASButtonNode.mm; sourceTree = ""; }; EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AsyncDisplayKitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1149,6 +1155,8 @@ 25B171EA1C12242700508A7A /* Data Controller */ = { isa = PBXGroup; children = ( + DEC447B31C2B9DBC00C8CBD1 /* ASDelegateProxy.h */, + DEC447B41C2B9DBC00C8CBD1 /* ASDelegateProxy.m */, 251B8EF21BBB3D690087C538 /* ASCollectionDataController.h */, 251B8EF31BBB3D690087C538 /* ASCollectionDataController.mm */, 464052191A3F83C40061C0BA /* ASDataController.h */, @@ -1264,6 +1272,7 @@ 18C2ED7E1B9B7DE800F627B3 /* ASCollectionNode.h in Headers */, 257754C01BEE458E00737CA5 /* ASTextNodeWordKerner.h in Headers */, AC3C4A511A1139C100143C57 /* ASCollectionView.h in Headers */, + DEC447B51C2B9DBC00C8CBD1 /* ASDelegateProxy.h in Headers */, 205F0E1D1B373A2C007741D0 /* ASCollectionViewLayoutController.h in Headers */, AC3C4A541A113EEC00143C57 /* ASCollectionViewProtocols.h in Headers */, 058D0A49195D05CB00B7D73C /* ASControlNode+Subclasses.h in Headers */, @@ -1432,6 +1441,7 @@ 34EFC7791B701D3600AD841F /* ASLayoutSpecUtilities.h in Headers */, B350625C1B010F070018CF92 /* ASLog.h in Headers */, 0442850E1BAA64EC00D16268 /* ASMultidimensionalArrayUtils.h in Headers */, + DEC447B61C2B9DBC00C8CBD1 /* ASDelegateProxy.h in Headers */, B35062041B010EFD0018CF92 /* ASMultiplexImageNode.h in Headers */, DECBD6E81BE56E1900CF4905 /* ASButtonNode.h in Headers */, B35062241B010EFD0018CF92 /* ASMutableAttributedStringBuilder.h in Headers */, @@ -1687,6 +1697,7 @@ 0549634A1A1EA066000F8E56 /* ASBasicImageDownloader.mm in Sources */, 299DA1AA1A828D2900162D41 /* ASBatchContext.mm in Sources */, AC6456091B0A335000CF11B8 /* ASCellNode.m in Sources */, + DEC447B71C2B9DBC00C8CBD1 /* ASDelegateProxy.m in Sources */, ACF6ED1D1B17843500DA7C62 /* ASCenterLayoutSpec.mm in Sources */, 18C2ED801B9B7DE800F627B3 /* ASCollectionNode.m in Sources */, 92DD2FE41BF4B97E0074C9DD /* ASMapNode.mm in Sources */, @@ -1816,6 +1827,7 @@ 509E68621B3AEDA5009B9150 /* ASAbstractLayoutController.mm in Sources */, 254C6B861BF94F8A003EC431 /* ASTextKitContext.mm in Sources */, 34EFC7621B701CA400AD841F /* ASBackgroundLayoutSpec.mm in Sources */, + DEC447B81C2B9DBC00C8CBD1 /* ASDelegateProxy.m in Sources */, B35062141B010EFD0018CF92 /* ASBasicImageDownloader.mm in Sources */, B35062161B010EFD0018CF92 /* ASBatchContext.mm in Sources */, AC47D9421B3B891B00AAEE9D /* ASCellNode.m in Sources */, diff --git a/AsyncDisplayKit.xcworkspace/contents.xcworkspacedata b/AsyncDisplayKit.xcworkspace/contents.xcworkspacedata index 574f0ec1..5f740017 100644 --- a/AsyncDisplayKit.xcworkspace/contents.xcworkspacedata +++ b/AsyncDisplayKit.xcworkspace/contents.xcworkspacedata @@ -1,6 +1,12 @@ + + + + diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index 5d3d051b..73e61653 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -8,6 +8,7 @@ #import "ASAssert.h" #import "ASBatchFetching.h" +#import "ASDelegateProxy.h" #import "ASCollectionView.h" #import "ASCollectionNode.h" #import "ASCollectionDataController.h" @@ -22,87 +23,6 @@ static const NSUInteger kASCollectionViewAnimationNone = UITableViewRowAnimation static const ASSizeRange kInvalidSizeRange = {CGSizeZero, CGSizeZero}; static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; -#pragma mark - -#pragma mark Proxying. - -/** - * ASCollectionView intercepts and/or overrides a few of UICollectionView's critical data source and delegate methods. - * - * Any selector included in this function *MUST* be implemented by ASCollectionView. - */ -static BOOL _isInterceptedSelector(SEL sel) -{ - return ( - // handled by ASCollectionView node<->cell machinery - sel == @selector(collectionView:cellForItemAtIndexPath:) || - sel == @selector(collectionView:layout:sizeForItemAtIndexPath:) || - sel == @selector(collectionView:viewForSupplementaryElementOfKind:atIndexPath:) || - - // handled by ASRangeController - sel == @selector(numberOfSectionsInCollectionView:) || - sel == @selector(collectionView:numberOfItemsInSection:) || - - // used for ASRangeController visibility updates - sel == @selector(collectionView:willDisplayCell:forItemAtIndexPath:) || - sel == @selector(collectionView:didEndDisplayingCell:forItemAtIndexPath:) || - - // used for batch fetching API - sel == @selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:) - ); -} - - -/** - * Stand-in for UICollectionViewDataSource and UICollectionViewDelegate. Any method calls we intercept are routed to ASCollectionView; - * everything else leaves AsyncDisplayKit safely and arrives at the original intended data source and delegate. - */ -@interface _ASCollectionViewProxy : NSProxy -- (instancetype)initWithTarget:(id)target interceptor:(ASCollectionView *)interceptor; -@end - -@implementation _ASCollectionViewProxy { - id __weak _target; - ASCollectionView * __weak _interceptor; -} - -- (instancetype)initWithTarget:(id)target interceptor:(ASCollectionView *)interceptor -{ - // -[NSProxy init] is undefined - if (!self) { - return nil; - } - - ASDisplayNodeAssert(target, @"target must not be nil"); - ASDisplayNodeAssert(interceptor, @"interceptor must not be nil"); - - _target = target; - _interceptor = interceptor; - - return self; -} - -- (BOOL)respondsToSelector:(SEL)aSelector -{ - ASDisplayNodeAssert(_target, @"target must not be nil"); // catch weak ref's being nilled early - ASDisplayNodeAssert(_interceptor, @"interceptor must not be nil"); - - return (_isInterceptedSelector(aSelector) || [_target respondsToSelector:aSelector]); -} - -- (id)forwardingTargetForSelector:(SEL)aSelector -{ - ASDisplayNodeAssert(_target, @"target must not be nil"); // catch weak ref's being nilled early - ASDisplayNodeAssert(_interceptor, @"interceptor must not be nil"); - - if (_isInterceptedSelector(aSelector)) { - return _interceptor; - } - - return [_target respondsToSelector:aSelector] ? _target : nil; -} - -@end - #pragma mark - #pragma mark ASCellNode<->UICollectionViewCell bridging. @@ -138,9 +58,9 @@ static BOOL _isInterceptedSelector(SEL sel) #pragma mark - #pragma mark ASCollectionView. -@interface ASCollectionView () { - _ASCollectionViewProxy *_proxyDataSource; - _ASCollectionViewProxy *_proxyDelegate; +@interface ASCollectionView () { + ASCollectionViewProxy *_proxyDataSource; + ASCollectionViewProxy *_proxyDelegate; ASCollectionDataController *_dataController; ASRangeController *_rangeController; @@ -155,6 +75,7 @@ static BOOL _isInterceptedSelector(SEL sel) BOOL _collectionViewLayoutImplementsInsetSection; BOOL _asyncDataSourceImplementsConstrainedSizeForNode; BOOL _queuedNodeSizeUpdate; + BOOL _isDeallocating; ASBatchContext *_batchContext; @@ -244,6 +165,12 @@ static BOOL _isInterceptedSelector(SEL sel) _layoutInspector = [self flowLayoutInspector]; } + _proxyDelegate = [[ASCollectionViewProxy alloc] initWithTarget:nil interceptor:self]; + super.delegate = (id)_proxyDelegate; + + _proxyDataSource = [[ASCollectionViewProxy alloc] initWithTarget:nil interceptor:self]; + super.dataSource = (id)_proxyDataSource; + _registeredSupplementaryKinds = [NSMutableSet set]; self.backgroundColor = [UIColor whiteColor]; @@ -255,10 +182,10 @@ static BOOL _isInterceptedSelector(SEL sel) - (void)dealloc { - // Sometimes the UIKit classes can call back to their delegate even during deallocation. - // This bug might be iOS 7-specific. - super.delegate = nil; - super.dataSource = nil; + // Sometimes the UIKit classes can call back to their delegate even during deallocation, due to animation completion blocks etc. + _isDeallocating = YES; + [self setAsyncDelegate:nil]; + [self setAsyncDataSource:nil]; } /** @@ -312,24 +239,35 @@ static BOOL _isInterceptedSelector(SEL sel) ASDisplayNodeAssert(delegate == nil, @"ASCollectionView uses asyncDelegate, not UICollectionView's delegate property."); } +- (void)proxyTargetHasDeallocated:(ASDelegateProxy *)proxy +{ + if (proxy == _proxyDelegate) { + [self setAsyncDelegate:nil]; + } else if (proxy == _proxyDataSource) { + [self setAsyncDataSource:nil]; + } +} + - (void)setAsyncDataSource:(id)asyncDataSource { // Note: It's common to check if the value hasn't changed and short-circuit but we aren't doing that here to handle // the (common) case of nilling the asyncDataSource in the ViewController's dealloc. In this case our _asyncDataSource // will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to nil out - // super.dataSource in this case because calls to _ASTableViewProxy will start failing and cause crashes. + // super.dataSource in this case because calls to ASCollectionViewProxy will start failing and cause crashes. + + super.dataSource = nil; if (asyncDataSource == nil) { - super.dataSource = nil; _asyncDataSource = nil; - _proxyDataSource = nil; + _proxyDataSource = _isDeallocating ? nil : [[ASCollectionViewProxy alloc] initWithTarget:nil interceptor:self]; _asyncDataSourceImplementsConstrainedSizeForNode = NO; } else { _asyncDataSource = asyncDataSource; - _proxyDataSource = [[_ASCollectionViewProxy alloc] initWithTarget:_asyncDataSource interceptor:self]; - super.dataSource = (id)_proxyDataSource; + _proxyDataSource = [[ASCollectionViewProxy alloc] initWithTarget:_asyncDataSource interceptor:self]; _asyncDataSourceImplementsConstrainedSizeForNode = ([_asyncDataSource respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)] ? 1 : 0); } + + super.dataSource = (id)_proxyDataSource; } - (void)setAsyncDelegate:(id)asyncDelegate @@ -337,22 +275,25 @@ static BOOL _isInterceptedSelector(SEL sel) // Note: It's common to check if the value hasn't changed and short-circuit but we aren't doing that here to handle // the (common) case of nilling the asyncDelegate in the ViewController's dealloc. In this case our _asyncDelegate // will return as nil (ARC magic) even though the _proxyDelegate still exists. It's really important to nil out - // super.delegate in this case because calls to _ASTableViewProxy will start failing and cause crashes. + // super.delegate in this case because calls to ASCollectionViewProxy will start failing and cause crashes. + + // Order is important here, the asyncDelegate must be callable while nilling super.delegate to avoid random crashes + // in UIScrollViewAccessibility. + + super.delegate = nil; if (asyncDelegate == nil) { - // order is important here, the delegate must be callable while nilling super.delegate to avoid random crashes - // in UIScrollViewAccessibility. - super.delegate = nil; _asyncDelegate = nil; - _proxyDelegate = nil; + _proxyDelegate = _isDeallocating ? nil : [[ASCollectionViewProxy alloc] initWithTarget:nil interceptor:self]; _asyncDelegateImplementsInsetSection = NO; } else { _asyncDelegate = asyncDelegate; - _proxyDelegate = [[_ASCollectionViewProxy alloc] initWithTarget:_asyncDelegate interceptor:self]; - super.delegate = (id)_proxyDelegate; + _proxyDelegate = [[ASCollectionViewProxy alloc] initWithTarget:_asyncDelegate interceptor:self]; _asyncDelegateImplementsInsetSection = ([_asyncDelegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)] ? 1 : 0); } + super.delegate = (id)_proxyDelegate; + [_layoutInspector didChangeCollectionViewDelegate:asyncDelegate]; } diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index ddb68380..8d799b5b 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -13,6 +13,7 @@ #import "ASBatchFetching.h" #import "ASChangeSetDataController.h" #import "ASCollectionViewLayoutController.h" +#import "ASDelegateProxy.h" #import "ASDisplayNode+FrameworkPrivate.h" #import "ASInternalHelpers.h" #import "ASLayout.h" @@ -24,87 +25,6 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; //#define LOG(...) NSLog(__VA_ARGS__) #define LOG(...) -#pragma mark - -#pragma mark Proxying. - -/** - * ASTableView intercepts and/or overrides a few of UITableView's critical data source and delegate methods. - * - * Any selector included in this function *MUST* be implemented by ASTableView. - */ -static BOOL _isInterceptedSelector(SEL sel) -{ - return ( - // handled by ASTableView node<->cell machinery - sel == @selector(tableView:cellForRowAtIndexPath:) || - sel == @selector(tableView:heightForRowAtIndexPath:) || - - // handled by ASRangeController - sel == @selector(numberOfSectionsInTableView:) || - sel == @selector(tableView:numberOfRowsInSection:) || - - // used for ASRangeController visibility updates - sel == @selector(tableView:willDisplayCell:forRowAtIndexPath:) || - sel == @selector(tableView:didEndDisplayingCell:forRowAtIndexPath:) || - - // used for batch fetching API - sel == @selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:) - ); -} - - -/** - * Stand-in for UITableViewDataSource and UITableViewDelegate. Any method calls we intercept are routed to ASTableView; - * everything else leaves AsyncDisplayKit safely and arrives at the original intended data source and delegate. - */ -@interface _ASTableViewProxy : NSProxy -- (instancetype)initWithTarget:(id)target interceptor:(ASTableView *)interceptor; -@end - -@implementation _ASTableViewProxy { - id __weak _target; - ASTableView * __weak _interceptor; -} - -- (instancetype)initWithTarget:(id)target interceptor:(ASTableView *)interceptor -{ - // -[NSProxy init] is undefined - if (!self) { - return nil; - } - - ASDisplayNodeAssert(target, @"target must not be nil"); - ASDisplayNodeAssert(interceptor, @"interceptor must not be nil"); - - _target = target; - _interceptor = interceptor; - - return self; -} - -- (BOOL)respondsToSelector:(SEL)aSelector -{ - ASDisplayNodeAssert(_target, @"target must not be nil"); // catch weak ref's being nilled early - ASDisplayNodeAssert(_interceptor, @"interceptor must not be nil"); - - return (_isInterceptedSelector(aSelector) || [_target respondsToSelector:aSelector]); -} - -- (id)forwardingTargetForSelector:(SEL)aSelector -{ - ASDisplayNodeAssert(_target, @"target must not be nil"); // catch weak ref's being nilled early - ASDisplayNodeAssert(_interceptor, @"interceptor must not be nil"); - - if (_isInterceptedSelector(aSelector)) { - return _interceptor; - } - - return [_target respondsToSelector:aSelector] ? _target : nil; -} - -@end - - #pragma mark - #pragma mark ASCellNode<->UITableViewCell bridging. @@ -156,13 +76,12 @@ static BOOL _isInterceptedSelector(SEL sel) @end - #pragma mark - #pragma mark ASTableView -@interface ASTableView () { - _ASTableViewProxy *_proxyDataSource; - _ASTableViewProxy *_proxyDelegate; +@interface ASTableView () { + ASTableViewProxy *_proxyDataSource; + ASTableViewProxy *_proxyDelegate; ASFlowLayoutController *_layoutController; @@ -180,6 +99,7 @@ static BOOL _isInterceptedSelector(SEL sel) CGFloat _nodesConstrainedWidth; BOOL _ignoreNodesConstrainedWidthChange; BOOL _queuedNodeHeightUpdate; + BOOL _isDeallocating; } @property (atomic, assign) BOOL asyncDataSourceLocked; @@ -224,6 +144,12 @@ static BOOL _isInterceptedSelector(SEL sel) // If the initial size is 0, expect a size change very soon which is part of the initial configuration // and should not trigger a relayout. _ignoreNodesConstrainedWidthChange = (_nodesConstrainedWidth == 0); + + _proxyDelegate = [[ASTableViewProxy alloc] initWithTarget:nil interceptor:self]; + super.delegate = (id)_proxyDelegate; + + _proxyDataSource = [[ASTableViewProxy alloc] initWithTarget:nil interceptor:self]; + super.dataSource = (id)_proxyDataSource; [self registerClass:_ASTableViewCell.class forCellReuseIdentifier:kCellReuseIdentifier]; } @@ -265,9 +191,9 @@ static BOOL _isInterceptedSelector(SEL sel) - (void)dealloc { // Sometimes the UIKit classes can call back to their delegate even during deallocation. - // This bug might be iOS 7-specific. - super.delegate = nil; - super.dataSource = nil; + _isDeallocating = YES; + [self setAsyncDelegate:nil]; + [self setAsyncDataSource:nil]; } #pragma mark - @@ -290,17 +216,19 @@ static BOOL _isInterceptedSelector(SEL sel) // Note: It's common to check if the value hasn't changed and short-circuit but we aren't doing that here to handle // the (common) case of nilling the asyncDataSource in the ViewController's dealloc. In this case our _asyncDataSource // will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to nil out - // super.dataSource in this case because calls to _ASTableViewProxy will start failing and cause crashes. - + // super.dataSource in this case because calls to ASTableViewProxy will start failing and cause crashes. + + super.dataSource = nil; + if (asyncDataSource == nil) { - super.dataSource = nil; _asyncDataSource = nil; - _proxyDataSource = nil; + _proxyDataSource = _isDeallocating ? nil : [[ASTableViewProxy alloc] initWithTarget:nil interceptor:self]; } else { _asyncDataSource = asyncDataSource; - _proxyDataSource = [[_ASTableViewProxy alloc] initWithTarget:_asyncDataSource interceptor:self]; - super.dataSource = (id)_proxyDataSource; + _proxyDataSource = [[ASTableViewProxy alloc] initWithTarget:_asyncDataSource interceptor:self]; } + + super.dataSource = (id)_proxyDataSource; } - (void)setAsyncDelegate:(id)asyncDelegate @@ -308,18 +236,30 @@ static BOOL _isInterceptedSelector(SEL sel) // Note: It's common to check if the value hasn't changed and short-circuit but we aren't doing that here to handle // the (common) case of nilling the asyncDelegate in the ViewController's dealloc. In this case our _asyncDelegate // will return as nil (ARC magic) even though the _proxyDelegate still exists. It's really important to nil out - // super.delegate in this case because calls to _ASTableViewProxy will start failing and cause crashes. + // super.delegate in this case because calls to ASTableViewProxy will start failing and cause crashes. + + // Order is important here, the asyncDelegate must be callable while nilling super.delegate to avoid random crashes + // in UIScrollViewAccessibility. + super.delegate = nil; + if (asyncDelegate == nil) { - // order is important here, the delegate must be callable while nilling super.delegate to avoid random crashes - // in UIScrollViewAccessibility. - super.delegate = nil; _asyncDelegate = nil; - _proxyDelegate = nil; + _proxyDelegate = _isDeallocating ? nil : [[ASTableViewProxy alloc] initWithTarget:nil interceptor:self]; } else { _asyncDelegate = asyncDelegate; - _proxyDelegate = [[_ASTableViewProxy alloc] initWithTarget:asyncDelegate interceptor:self]; - super.delegate = (id)_proxyDelegate; + _proxyDelegate = [[ASTableViewProxy alloc] initWithTarget:_asyncDelegate interceptor:self]; + } + + super.delegate = (id)_proxyDelegate; +} + +- (void)proxyTargetHasDeallocated:(ASDelegateProxy *)proxy +{ + if (proxy == _proxyDelegate) { + [self setAsyncDelegate:nil]; + } else if (proxy == _proxyDataSource) { + [self setAsyncDataSource:nil]; } } diff --git a/AsyncDisplayKit/Details/ASDelegateProxy.h b/AsyncDisplayKit/Details/ASDelegateProxy.h new file mode 100644 index 00000000..ca5ae5da --- /dev/null +++ b/AsyncDisplayKit/Details/ASDelegateProxy.h @@ -0,0 +1,51 @@ +/* Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +@class ASDelegateProxy; +@protocol ASDelegateProxyInterceptor +@required +// Called if the target object is discovered to be nil if it had been non-nil at init time. +// This happens if the object is deallocated, because the proxy must maintain a weak reference to avoid cycles. +// Though the target object may become nil, the interceptor must not; it is assumed the interceptor owns the proxy. +- (void)proxyTargetHasDeallocated:(ASDelegateProxy *)proxy; +@end + +/** + * Stand-in for delegates like UITableView or UICollectionView's delegate / dataSource. + * Any selectors flagged by "interceptsSelector" are routed to the interceptor object and are not delivered to the target. + * Everything else leaves AsyncDisplayKit safely and arrives at the original target object. + */ + +@interface ASDelegateProxy : NSProxy + +- (instancetype)initWithTarget:(id)target interceptor:(id )interceptor; + +// This method must be overridden by a subclass. +- (BOOL)interceptsSelector:(SEL)selector; + +@end + +/** + * ASTableView intercepts and/or overrides a few of UITableView's critical data source and delegate methods. + * + * Any selector included in this function *MUST* be implemented by ASTableView. + */ + +@interface ASTableViewProxy : ASDelegateProxy +@end + +/** + * ASCollectionView intercepts and/or overrides a few of UICollectionView's critical data source and delegate methods. + * + * Any selector included in this function *MUST* be implemented by ASCollectionView. + */ + +@interface ASCollectionViewProxy : ASDelegateProxy +@end diff --git a/AsyncDisplayKit/Details/ASDelegateProxy.m b/AsyncDisplayKit/Details/ASDelegateProxy.m new file mode 100644 index 00000000..baaff1e6 --- /dev/null +++ b/AsyncDisplayKit/Details/ASDelegateProxy.m @@ -0,0 +1,117 @@ +/* Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "ASDelegateProxy.h" +#import "ASTableView.h" +#import "ASCollectionView.h" +#import "ASAssert.h" + +@implementation ASTableViewProxy + +- (BOOL)interceptsSelector:(SEL)selector +{ + return ( + // handled by ASTableView node<->cell machinery + selector == @selector(tableView:cellForRowAtIndexPath:) || + selector == @selector(tableView:heightForRowAtIndexPath:) || + + // handled by ASRangeController + selector == @selector(numberOfSectionsInTableView:) || + selector == @selector(tableView:numberOfRowsInSection:) || + + // used for ASRangeController visibility updates + selector == @selector(tableView:willDisplayCell:forRowAtIndexPath:) || + selector == @selector(tableView:didEndDisplayingCell:forRowAtIndexPath:) || + + // used for batch fetching API + selector == @selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:) + ); +} + +@end + +@implementation ASCollectionViewProxy + +- (BOOL)interceptsSelector:(SEL)selector +{ + return ( + // handled by ASCollectionView node<->cell machinery + selector == @selector(collectionView:cellForItemAtIndexPath:) || + selector == @selector(collectionView:layout:sizeForItemAtIndexPath:) || + selector == @selector(collectionView:viewForSupplementaryElementOfKind:atIndexPath:) || + + // handled by ASRangeController + selector == @selector(numberOfSectionsInCollectionView:) || + selector == @selector(collectionView:numberOfItemsInSection:) || + + // used for ASRangeController visibility updates + selector == @selector(collectionView:willDisplayCell:forItemAtIndexPath:) || + selector == @selector(collectionView:didEndDisplayingCell:forItemAtIndexPath:) || + + // used for batch fetching API + selector == @selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:) + ); +} + +@end + +@implementation ASDelegateProxy { + id __weak _target; + id __weak _interceptor; +} + +- (instancetype)initWithTarget:(id )target interceptor:(id )interceptor +{ + // -[NSProxy init] is undefined + if (!self) { + return nil; + } + + ASDisplayNodeAssert(interceptor, @"interceptor must not be nil"); + + _target = target ? : [NSNull null]; + _interceptor = interceptor; + + return self; +} + +- (BOOL)respondsToSelector:(SEL)aSelector +{ + ASDisplayNodeAssert(_interceptor, @"interceptor must not be nil"); + + if ([self interceptsSelector:aSelector]) { + return YES; + } else { + // Also return NO if _target has become nil due to zeroing weak reference (or placeholder initialization). + return [_target respondsToSelector:aSelector]; + } +} + +- (id)forwardingTargetForSelector:(SEL)aSelector +{ + ASDisplayNodeAssert(_interceptor, @"interceptor must not be nil"); + + if ([self interceptsSelector:aSelector]) { + return _interceptor; + } else { + if (_target) { + return [_target respondsToSelector:aSelector] ? _target : nil; + } else { + [_interceptor proxyTargetHasDeallocated:self]; + return nil; + } + } +} + +- (BOOL)interceptsSelector:(SEL)selector +{ + ASDisplayNodeAssert(NO, @"This method must be overridden by subclasses."); + return NO; +} + +@end diff --git a/AsyncDisplayKitTests/ASBasicImageDownloaderTests.m b/AsyncDisplayKitTests/ASBasicImageDownloaderTests.m index 11271b23..9def4240 100644 --- a/AsyncDisplayKitTests/ASBasicImageDownloaderTests.m +++ b/AsyncDisplayKitTests/ASBasicImageDownloaderTests.m @@ -11,45 +11,38 @@ #import // Z in the name to delay running until after the test instance is operating normally. -@interface ASZBasicImageDownloaderTests : XCTestCase +@interface ASBasicImageDownloaderTests : XCTestCase @end -@implementation ASZBasicImageDownloaderTests +@implementation ASBasicImageDownloaderTests - (void)testAsynchronouslyDownloadTheSameURLTwice { ASBasicImageDownloader *downloader = [ASBasicImageDownloader sharedImageDownloader]; NSURL *URL = [NSURL URLWithString:@"http://wrongPath/wrongResource.png"]; - - dispatch_group_t group = dispatch_group_create(); - + __block BOOL firstDone = NO; - dispatch_group_enter(group); [downloader downloadImageWithURL:URL callbackQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) downloadProgressBlock:nil completion:^(CGImageRef image, NSError *error) { firstDone = YES; - dispatch_group_leave(group); }]; __block BOOL secondDone = NO; - dispatch_group_enter(group); [downloader downloadImageWithURL:URL callbackQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) downloadProgressBlock:nil completion:^(CGImageRef image, NSError *error) { secondDone = YES; - dispatch_group_leave(group); }]; - - XCTAssert(0 == dispatch_group_wait(group, dispatch_time(0, 10 * 1000000000)), @"URL loading takes too long"); - - XCTAssert(firstDone && secondDone, @"Not all handlers has been called"); + + sleep(3); + XCTAssert(firstDone && secondDone, @"Not all ASBasicImageDownloader completion handlers have been called after 3 seconds"); } @end diff --git a/examples/ASCollectionView/Sample.xcodeproj/project.pbxproj b/examples/ASCollectionView/Sample.xcodeproj/project.pbxproj index 56aef5f7..3cdc9251 100644 --- a/examples/ASCollectionView/Sample.xcodeproj/project.pbxproj +++ b/examples/ASCollectionView/Sample.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ AC3C4A6A1A11F47200143C57 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AC3C4A691A11F47200143C57 /* ViewController.m */; }; AC3C4A8E1A11F80C00143C57 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AC3C4A8D1A11F80C00143C57 /* Images.xcassets */; }; FABD6D156A3EB118497E5CE6 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F02BAF78E68BC56FD8C161B7 /* libPods.a */; }; + FC3FCA801C2B1564009F6D6D /* PresentingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FC3FCA7F1C2B1564009F6D6D /* PresentingViewController.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -34,6 +35,8 @@ AC3C4A8D1A11F80C00143C57 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; CD1ABB23007FEDB31D8C1978 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; F02BAF78E68BC56FD8C161B7 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; + FC3FCA7E1C2B1564009F6D6D /* PresentingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PresentingViewController.h; sourceTree = ""; }; + FC3FCA7F1C2B1564009F6D6D /* PresentingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PresentingViewController.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -82,6 +85,8 @@ AC3C4A661A11F47200143C57 /* AppDelegate.m */, AC3C4A681A11F47200143C57 /* ViewController.h */, AC3C4A691A11F47200143C57 /* ViewController.m */, + FC3FCA7E1C2B1564009F6D6D /* PresentingViewController.h */, + FC3FCA7F1C2B1564009F6D6D /* PresentingViewController.m */, AC3C4A8D1A11F80C00143C57 /* Images.xcassets */, AC3C4A611A11F47200143C57 /* Supporting Files */, 9B92C87F1BC17D3000EE46B2 /* SupplementaryNode.h */, @@ -125,7 +130,6 @@ AC3C4A5B1A11F47200143C57 /* Frameworks */, AC3C4A5C1A11F47200143C57 /* Resources */, A6902C454C7661D0D277AC62 /* Copy Pods Resources */, - EC37EEC9933F5786936BFE7C /* Embed Pods Frameworks */, ); buildRules = ( ); @@ -196,21 +200,6 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; showEnvVarsInLog = 0; }; - EC37EEC9933F5786936BFE7C /* 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; - }; F868CFBB21824CC9521B6588 /* Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -236,6 +225,7 @@ 25FDEC921BF31EE700CEB123 /* ItemNode.m in Sources */, AC3C4A6A1A11F47200143C57 /* ViewController.m in Sources */, 9B92C8811BC17D3000EE46B2 /* SupplementaryNode.m in Sources */, + FC3FCA801C2B1564009F6D6D /* PresentingViewController.m in Sources */, AC3C4A671A11F47200143C57 /* AppDelegate.m in Sources */, AC3C4A641A11F47200143C57 /* main.m in Sources */, ); diff --git a/examples/ASCollectionView/Sample.xcworkspace/contents.xcworkspacedata b/examples/ASCollectionView/Sample.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..7b5a2f30 --- /dev/null +++ b/examples/ASCollectionView/Sample.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/examples/ASCollectionView/Sample/AppDelegate.h b/examples/ASCollectionView/Sample/AppDelegate.h index 2aa29369..80b7fb3d 100644 --- a/examples/ASCollectionView/Sample/AppDelegate.h +++ b/examples/ASCollectionView/Sample/AppDelegate.h @@ -11,6 +11,8 @@ #import +#define SIMULATE_WEB_RESPONSE 0 + @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; diff --git a/examples/ASCollectionView/Sample/AppDelegate.m b/examples/ASCollectionView/Sample/AppDelegate.m index a979170a..19ceedd9 100644 --- a/examples/ASCollectionView/Sample/AppDelegate.m +++ b/examples/ASCollectionView/Sample/AppDelegate.m @@ -11,6 +11,7 @@ #import "AppDelegate.h" +#import "PresentingViewController.h" #import "ViewController.h" @implementation AppDelegate @@ -31,10 +32,14 @@ - (void)pushNewViewControllerAnimated:(BOOL)animated { UINavigationController *navController = (UINavigationController *)self.window.rootViewController; - + +#if SIMULATE_WEB_RESPONSE + UIViewController *viewController = [[PresentingViewController alloc] init]; +#else UIViewController *viewController = [[ViewController alloc] init]; viewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Push Another Copy" style:UIBarButtonItemStylePlain target:self action:@selector(pushNewViewController)]; - +#endif + [navController pushViewController:viewController animated:animated]; } diff --git a/examples/ASCollectionView/Sample/PresentingViewController.h b/examples/ASCollectionView/Sample/PresentingViewController.h new file mode 100644 index 00000000..bd2308fa --- /dev/null +++ b/examples/ASCollectionView/Sample/PresentingViewController.h @@ -0,0 +1,13 @@ +// +// PresentingViewController.h +// Sample +// +// Created by Tom King on 12/23/15. +// Copyright © 2015 Facebook. All rights reserved. +// + +#import + +@interface PresentingViewController : UIViewController + +@end diff --git a/examples/ASCollectionView/Sample/PresentingViewController.m b/examples/ASCollectionView/Sample/PresentingViewController.m new file mode 100644 index 00000000..49c65e69 --- /dev/null +++ b/examples/ASCollectionView/Sample/PresentingViewController.m @@ -0,0 +1,30 @@ +// +// PresentingViewController.m +// Sample +// +// Created by Tom King on 12/23/15. +// Copyright © 2015 Facebook. All rights reserved. +// + +#import "PresentingViewController.h" +#import "ViewController.h" + +@interface PresentingViewController () + +@end + +@implementation PresentingViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Push Details" style:UIBarButtonItemStylePlain target:self action:@selector(pushNewViewController)]; +} + +- (void)pushNewViewController +{ + ViewController *controller = [[ViewController alloc] init]; + [self.navigationController pushViewController:controller animated:true]; +} + +@end diff --git a/examples/ASCollectionView/Sample/ViewController.m b/examples/ASCollectionView/Sample/ViewController.m index a9d3e12a..00aea567 100644 --- a/examples/ASCollectionView/Sample/ViewController.m +++ b/examples/ASCollectionView/Sample/ViewController.m @@ -18,6 +18,7 @@ @interface ViewController () { ASCollectionView *_collectionView; + NSArray *_data; } @end @@ -37,7 +38,7 @@ layout.headerReferenceSize = CGSizeMake(50.0, 50.0); layout.footerReferenceSize = CGSizeMake(50.0, 50.0); - _collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout asyncDataFetching:YES]; + _collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; _collectionView.asyncDataSource = self; _collectionView.asyncDelegate = self; _collectionView.backgroundColor = [UIColor whiteColor]; @@ -45,8 +46,10 @@ [_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; } @@ -56,6 +59,31 @@ [super viewDidLoad]; [self.view addSubview:_collectionView]; + +#if SIMULATE_WEB_RESPONSE + __weak typeof(self) weakSelf = self; + void(^mockWebService)() = ^{ + NSLog(@"ViewController \"got data from a web service\""); + ViewController *strongSelf = weakSelf; + if (strongSelf != nil) + { + NSLog(@"ViewController is not nil"); + strongSelf->_data = [[NSArray alloc] init]; + [strongSelf->_collectionView performBatchUpdates:^{ + [strongSelf->_collectionView insertSections:[[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, 100)]]; + } completion:nil]; + NSLog(@"ViewController finished updating collectionView"); + } + else { + NSLog(@"ViewController is nil - won't update collectionView"); + } + }; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), mockWebService); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self.navigationController popViewControllerAnimated:YES]; + }); +#endif } - (void)viewWillLayoutSubviews @@ -101,7 +129,11 @@ - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { +#if SIMULATE_WEB_RESPONSE + return _data == nil ? 0 : 100; +#else return 100; +#endif } - (void)collectionViewLockDataSource:(ASCollectionView *)collectionView @@ -125,4 +157,11 @@ return UIEdgeInsetsMake(20.0, 20.0, 20.0, 20.0); } +#if SIMULATE_WEB_RESPONSE +-(void)dealloc +{ + NSLog(@"ViewController is deallocing"); +} +#endif + @end From 8b3f3351abad83735aac515ce9e79f5eb477fa74 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Wed, 23 Dec 2015 21:53:42 -0800 Subject: [PATCH 46/60] Logging for test failures that are only occurring on build server with iOS 8.1 simulator... --- AsyncDisplayKit/ASCollectionView.mm | 6 ++++++ AsyncDisplayKit/Details/ASDelegateProxy.m | 6 +----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index 73e61653..c9f52c14 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -184,8 +184,10 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; { // Sometimes the UIKit classes can call back to their delegate even during deallocation, due to animation completion blocks etc. _isDeallocating = YES; + NSLog(@"before dealloc - delegate - %@, datasource - %@, proxyDelegate - %@, proxyDatasource - %@", self.asyncDelegate, self.asyncDataSource, _proxyDelegate, _proxyDataSource); [self setAsyncDelegate:nil]; [self setAsyncDataSource:nil]; + NSLog(@"after dealloc - delegate - %@, datasource - %@, proxyDelegate - %@, proxyDatasource - %@", self.asyncDelegate, self.asyncDataSource, _proxyDelegate, _proxyDataSource); } /** @@ -267,6 +269,8 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; _asyncDataSourceImplementsConstrainedSizeForNode = ([_asyncDataSource respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)] ? 1 : 0); } + NSLog(@"setAsyncDataSource - %@, proxy - %@, deallocating - %d", asyncDataSource, _proxyDataSource, _isDeallocating); + super.dataSource = (id)_proxyDataSource; } @@ -292,6 +296,8 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; _asyncDelegateImplementsInsetSection = ([_asyncDelegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)] ? 1 : 0); } + NSLog(@"setAsyncDelegate - %@, proxy - %@, deallocating - %d", asyncDelegate, _proxyDelegate, _isDeallocating); + super.delegate = (id)_proxyDelegate; [_layoutInspector didChangeCollectionViewDelegate:asyncDelegate]; diff --git a/AsyncDisplayKit/Details/ASDelegateProxy.m b/AsyncDisplayKit/Details/ASDelegateProxy.m index baaff1e6..cd64c482 100644 --- a/AsyncDisplayKit/Details/ASDelegateProxy.m +++ b/AsyncDisplayKit/Details/ASDelegateProxy.m @@ -82,10 +82,8 @@ - (BOOL)respondsToSelector:(SEL)aSelector { - ASDisplayNodeAssert(_interceptor, @"interceptor must not be nil"); - if ([self interceptsSelector:aSelector]) { - return YES; + return (_interceptor != nil); } else { // Also return NO if _target has become nil due to zeroing weak reference (or placeholder initialization). return [_target respondsToSelector:aSelector]; @@ -94,8 +92,6 @@ - (id)forwardingTargetForSelector:(SEL)aSelector { - ASDisplayNodeAssert(_interceptor, @"interceptor must not be nil"); - if ([self interceptsSelector:aSelector]) { return _interceptor; } else { From 15826b58e424a83b3af348ee082f598d7f934a4c Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Wed, 23 Dec 2015 22:24:17 -0800 Subject: [PATCH 47/60] Remove extra logging for build server debugging. --- AsyncDisplayKit/ASCollectionView.mm | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index c9f52c14..c044919b 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -184,10 +184,8 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; { // Sometimes the UIKit classes can call back to their delegate even during deallocation, due to animation completion blocks etc. _isDeallocating = YES; - NSLog(@"before dealloc - delegate - %@, datasource - %@, proxyDelegate - %@, proxyDatasource - %@", self.asyncDelegate, self.asyncDataSource, _proxyDelegate, _proxyDataSource); [self setAsyncDelegate:nil]; [self setAsyncDataSource:nil]; - NSLog(@"after dealloc - delegate - %@, datasource - %@, proxyDelegate - %@, proxyDatasource - %@", self.asyncDelegate, self.asyncDataSource, _proxyDelegate, _proxyDataSource); } /** @@ -269,8 +267,6 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; _asyncDataSourceImplementsConstrainedSizeForNode = ([_asyncDataSource respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)] ? 1 : 0); } - NSLog(@"setAsyncDataSource - %@, proxy - %@, deallocating - %d", asyncDataSource, _proxyDataSource, _isDeallocating); - super.dataSource = (id)_proxyDataSource; } @@ -295,9 +291,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; _proxyDelegate = [[ASCollectionViewProxy alloc] initWithTarget:_asyncDelegate interceptor:self]; _asyncDelegateImplementsInsetSection = ([_asyncDelegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)] ? 1 : 0); } - - NSLog(@"setAsyncDelegate - %@, proxy - %@, deallocating - %d", asyncDelegate, _proxyDelegate, _isDeallocating); - + super.delegate = (id)_proxyDelegate; [_layoutInspector didChangeCollectionViewDelegate:asyncDelegate]; From 27c151095b3a6d2454742eed62783eb17d125812 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Thu, 24 Dec 2015 17:06:57 -0800 Subject: [PATCH 48/60] [ASPagerNode] New API tweaks. Support setting delegate + dataSource on ASCollectionNode and ASTableNode without triggering view creation. --- AsyncDisplayKit/ASCollectionNode.h | 3 + AsyncDisplayKit/ASCollectionNode.m | 63 +++++++++++++++++++- AsyncDisplayKit/ASCollectionView.h | 4 ++ AsyncDisplayKit/ASPagerNode.h | 20 ++++++- AsyncDisplayKit/ASPagerNode.m | 49 +++++++++++---- AsyncDisplayKit/ASTableNode.h | 4 ++ AsyncDisplayKit/ASTableNode.m | 59 +++++++++++++++++- AsyncDisplayKit/ASTableView.h | 4 ++ AsyncDisplayKit/Details/ASDelegateProxy.h | 4 ++ AsyncDisplayKit/Details/ASDelegateProxy.m | 14 +++++ AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm | 45 +++++++------- 11 files changed, 230 insertions(+), 39 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionNode.h b/AsyncDisplayKit/ASCollectionNode.h index 8109c897..8dcdb793 100644 --- a/AsyncDisplayKit/ASCollectionNode.h +++ b/AsyncDisplayKit/ASCollectionNode.h @@ -17,6 +17,9 @@ - (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout; - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout; +@property (weak, nonatomic) id delegate; +@property (weak, nonatomic) id dataSource; + @property (nonatomic, readonly) ASCollectionView *view; /** diff --git a/AsyncDisplayKit/ASCollectionNode.m b/AsyncDisplayKit/ASCollectionNode.m index 8c74d62c..7cf49fbc 100644 --- a/AsyncDisplayKit/ASCollectionNode.m +++ b/AsyncDisplayKit/ASCollectionNode.m @@ -9,7 +9,19 @@ #import "ASCollectionNode.h" #import "ASDisplayNode+Subclasses.h" -@interface ASCollectionView (Internal) +@interface _ASCollectionPendingState : NSObject +@property (weak, nonatomic) id delegate; +@property (weak, nonatomic) id dataSource; +@end + +@implementation _ASCollectionPendingState +@end + +@interface ASCollectionNode () +@property (nonatomic) _ASCollectionPendingState *pendingState; +@end + +@interface ASCollectionView () - (instancetype)_initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout; @end @@ -29,12 +41,59 @@ - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout { - if (self = [super initWithViewBlock:^UIView *{ return [[ASCollectionView alloc] _initWithFrame:frame collectionViewLayout:layout]; }]) { + ASDisplayNodeViewBlock collectionViewBlock = ^UIView *{ + return [[ASCollectionView alloc] _initWithFrame:frame collectionViewLayout:layout]; + }; + + if (self = [super initWithViewBlock:collectionViewBlock]) { return self; } return nil; } +- (void)didLoad +{ + [super didLoad]; + + if (_pendingState) { + _ASCollectionPendingState *pendingState = _pendingState; + self.pendingState = nil; + + ASCollectionView *view = self.view; + view.asyncDelegate = pendingState.delegate; + view.asyncDataSource = pendingState.dataSource; + } +} + +- (_ASCollectionPendingState *)pendingState +{ + if (!_pendingState && ![self isNodeLoaded]) { + self.pendingState = [[_ASCollectionPendingState alloc] init]; + } + ASDisplayNodeAssert(![self isNodeLoaded] || !_pendingState, @"ASCollectionNode should not have a pendingState once it is loaded"); + return _pendingState; +} + +- (void)setDelegate:(id )delegate +{ + if ([self pendingState]) { + _pendingState.delegate = delegate; + } else { + ASDisplayNodeAssert([self isNodeLoaded], @"ASCollectionNode should be loaded if pendingState doesn't exist"); + self.view.asyncDelegate = delegate; + } +} + +- (void)setDataSource:(id )dataSource +{ + if ([self pendingState]) { + _pendingState.dataSource = dataSource; + } else { + ASDisplayNodeAssert([self isNodeLoaded], @"ASCollectionNode should be loaded if pendingState doesn't exist"); + self.view.asyncDataSource = dataSource; + } +} + - (ASCollectionView *)view { return (ASCollectionView *)[super view]; diff --git a/AsyncDisplayKit/ASCollectionView.h b/AsyncDisplayKit/ASCollectionView.h index 5d93fdcd..b0072e64 100644 --- a/AsyncDisplayKit/ASCollectionView.h +++ b/AsyncDisplayKit/ASCollectionView.h @@ -286,6 +286,8 @@ /** * This is a node-based UICollectionViewDataSource. */ +@protocol ASCollectionDataSource +@end @protocol ASCollectionViewDataSource /** @@ -347,6 +349,8 @@ /** * This is a node-based UICollectionViewDelegate. */ +@protocol ASCollectionDelegate +@end @protocol ASCollectionViewDelegate @optional diff --git a/AsyncDisplayKit/ASPagerNode.h b/AsyncDisplayKit/ASPagerNode.h index 36355c91..f2f69b61 100644 --- a/AsyncDisplayKit/ASPagerNode.h +++ b/AsyncDisplayKit/ASPagerNode.h @@ -12,7 +12,21 @@ @interface ASPagerNode : ASCollectionNode -@property (weak, nonatomic) id dataSource; +// Configures a default horizontal, paging flow layout with 0 inter-item spacing. +- (instancetype)init; + +// Initializer with custom-configured flow layout properties. +- (instancetype)initWithFlowLayout:(UICollectionViewFlowLayout *)flowLayout; + +// The underlying ASCollectionView object. +- (ASCollectionView *)collectionView; + +// Delegate is optional, and uses the same protocol as ASCollectionNode. +// This includes UIScrollViewDelegate as well as most methods from UICollectionViewDelegate, like willDisplay... +@property (weak, nonatomic) id delegate; + +// Data Source is required, and uses a different protocol from ASCollectionNode. +@property (weak, nonatomic) id dataSource; - (void)scrollToPageAtIndex:(NSInteger)index animated:(BOOL)animated; @@ -20,8 +34,10 @@ @protocol ASPagerNodeDataSource +// This method replaces -collectionView:numberOfItemsInSection: - (NSInteger)numberOfPagesInPagerNode:(ASPagerNode *)pagerNode; +// This method replaces -collectionView:nodeForItemAtIndexPath: - (ASCellNode *)pagerNode:(ASPagerNode *)pagerNode nodeAtIndex:(NSInteger)index; -@end \ No newline at end of file +@end diff --git a/AsyncDisplayKit/ASPagerNode.m b/AsyncDisplayKit/ASPagerNode.m index eead9a30..dbaaa973 100644 --- a/AsyncDisplayKit/ASPagerNode.m +++ b/AsyncDisplayKit/ASPagerNode.m @@ -7,11 +7,14 @@ // #import "ASPagerNode.h" +#import "ASDelegateProxy.h" #import @interface ASPagerNode () { UICollectionViewFlowLayout *_flowLayout; + ASPagerNodeProxy *_proxy; + id _pagerDataSource; } @end @@ -25,6 +28,11 @@ flowLayout.minimumInteritemSpacing = 0; flowLayout.minimumLineSpacing = 0; + return [self initWithFlowLayout:flowLayout]; +} + +- (instancetype)initWithFlowLayout:(UICollectionViewFlowLayout *)flowLayout +{ self = [super initWithCollectionViewLayout:flowLayout]; if (self != nil) { _flowLayout = flowLayout; @@ -32,17 +40,38 @@ return self; } +- (ASCollectionView *)collectionView +{ + return self.view; +} + +- (void)setDataSource:(id )pagerDataSource +{ + if (pagerDataSource != _pagerDataSource) { + _pagerDataSource = pagerDataSource; + _proxy = pagerDataSource ? [[ASPagerNodeProxy alloc] initWithTarget:pagerDataSource interceptor:self] : nil; + super.dataSource = _proxy; + } +} + +- (id )dataSource +{ + return _pagerDataSource; +} + - (void)didLoad { [super didLoad]; - self.view.asyncDataSource = self; - self.view.asyncDelegate = self; + ASCollectionView *cv = self.view; + cv.asyncDataSource = self; + cv.asyncDelegate = self; - self.view.pagingEnabled = YES; - self.view.allowsSelection = NO; - self.view.showsVerticalScrollIndicator = NO; - self.view.showsHorizontalScrollIndicator = NO; + cv.pagingEnabled = YES; + cv.allowsSelection = NO; + cv.showsVerticalScrollIndicator = NO; + cv.showsHorizontalScrollIndicator = NO; + cv.scrollsToTop = NO; ASRangeTuningParameters preloadParams = { .leadingBufferScreenfuls = 2.0, .trailingBufferScreenfuls = 2.0 }; ASRangeTuningParameters renderParams = { .leadingBufferScreenfuls = 1.0, .trailingBufferScreenfuls = 1.0 }; @@ -62,14 +91,14 @@ - (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]; + ASDisplayNodeAssert(_pagerDataSource != nil, @"ASPagerNode must have a data source to load paging nodes"); + return [_pagerDataSource 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]; + ASDisplayNodeAssert(_pagerDataSource != nil, @"ASPagerNode must have a data source to load paging nodes"); + return [_pagerDataSource numberOfPagesInPagerNode:self]; } - (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath diff --git a/AsyncDisplayKit/ASTableNode.h b/AsyncDisplayKit/ASTableNode.h index 026414be..d859df67 100644 --- a/AsyncDisplayKit/ASTableNode.h +++ b/AsyncDisplayKit/ASTableNode.h @@ -18,4 +18,8 @@ @property (nonatomic, readonly) ASTableView *view; +// These properties can be set without triggering the view to be created, so it's fine to set them in -init. +@property (weak, nonatomic) id delegate; +@property (weak, nonatomic) id dataSource; + @end diff --git a/AsyncDisplayKit/ASTableNode.m b/AsyncDisplayKit/ASTableNode.m index 11287a83..136c6843 100644 --- a/AsyncDisplayKit/ASTableNode.m +++ b/AsyncDisplayKit/ASTableNode.m @@ -8,18 +8,71 @@ #import "ASTableNode.h" +@interface _ASTablePendingState : NSObject +@property (weak, nonatomic) id delegate; +@property (weak, nonatomic) id dataSource; +@end + +@implementation _ASTablePendingState +@end + +@interface ASTableNode () +@property (nonatomic) _ASTablePendingState *pendingState; +@end + @implementation ASTableNode - (instancetype)initWithStyle:(UITableViewStyle)style { - if (self = [super initWithViewBlock:^UIView *{ - return [[ASTableView alloc] initWithFrame:CGRectZero style:style]; - }]) { + if (self = [super initWithViewBlock:^UIView *{ return [[ASTableView alloc] initWithFrame:CGRectZero style:style]; }]) { return self; } return nil; } +- (void)didLoad +{ + [super didLoad]; + + if (_pendingState) { + _ASTablePendingState *pendingState = _pendingState; + self.pendingState = nil; + + ASTableView *view = self.view; + view.asyncDelegate = pendingState.delegate; + view.asyncDataSource = pendingState.dataSource; + } +} + +- (_ASTablePendingState *)pendingState +{ + if (!_pendingState && ![self isNodeLoaded]) { + self.pendingState = [[_ASTablePendingState alloc] init]; + } + ASDisplayNodeAssert(![self isNodeLoaded] || !_pendingState, @"ASTableNode should not have a pendingState once it is loaded"); + return _pendingState; +} + +- (void)setDelegate:(id )delegate +{ + if ([self pendingState]) { + _pendingState.delegate = delegate; + } else { + ASDisplayNodeAssert([self isNodeLoaded], @"ASTableNode should be loaded if pendingState doesn't exist"); + self.view.asyncDelegate = delegate; + } +} + +- (void)setDataSource:(id )dataSource +{ + if ([self pendingState]) { + _pendingState.dataSource = dataSource; + } else { + ASDisplayNodeAssert([self isNodeLoaded], @"ASTableNode should be loaded if pendingState doesn't exist"); + self.view.asyncDataSource = dataSource; + } +} + - (ASTableView *)view { return (ASTableView *)[super view]; diff --git a/AsyncDisplayKit/ASTableView.h b/AsyncDisplayKit/ASTableView.h index 67c4b852..f6746874 100644 --- a/AsyncDisplayKit/ASTableView.h +++ b/AsyncDisplayKit/ASTableView.h @@ -280,6 +280,8 @@ /** * This is a node-based UITableViewDataSource. */ +@protocol ASTableDataSource +@end @protocol ASTableViewDataSource /** @@ -324,6 +326,8 @@ * Note that -tableView:heightForRowAtIndexPath: has been removed; instead, your custom ASCellNode subclasses are * responsible for deciding their preferred onscreen height in -calculateSizeThatFits:. */ +@protocol ASTableDelegate +@end @protocol ASTableViewDelegate @optional diff --git a/AsyncDisplayKit/Details/ASDelegateProxy.h b/AsyncDisplayKit/Details/ASDelegateProxy.h index ca5ae5da..850328a8 100644 --- a/AsyncDisplayKit/Details/ASDelegateProxy.h +++ b/AsyncDisplayKit/Details/ASDelegateProxy.h @@ -49,3 +49,7 @@ @interface ASCollectionViewProxy : ASDelegateProxy @end + +@interface ASPagerNodeProxy : ASDelegateProxy +@end + diff --git a/AsyncDisplayKit/Details/ASDelegateProxy.m b/AsyncDisplayKit/Details/ASDelegateProxy.m index cd64c482..8054b2b0 100644 --- a/AsyncDisplayKit/Details/ASDelegateProxy.m +++ b/AsyncDisplayKit/Details/ASDelegateProxy.m @@ -60,6 +60,20 @@ @end +@implementation ASPagerNodeProxy + +- (BOOL)interceptsSelector:(SEL)selector +{ + return ( + // handled by ASPagerNodeDataSource node<->cell machinery + selector == @selector(collectionView:nodeForItemAtIndexPath:) || + selector == @selector(collectionView:numberOfItemsInSection:) || + selector == @selector(collectionView:constrainedSizeForNodeAtIndexPath:) + ); +} + +@end + @implementation ASDelegateProxy { id __weak _target; id __weak _interceptor; diff --git a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm index f3460173..ae957559 100644 --- a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm @@ -39,33 +39,34 @@ - (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize { - CGSize size = { - constrainedSize.max.width, - constrainedSize.max.height - }; + CGSize maxConstrainedSize = CGSizeMake(constrainedSize.max.width, constrainedSize.max.height); + + NSArray *children = self.children; + NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:children.count]; - NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:self.children.count]; - for (id child in self.children) { - CGSize autoMaxSize = { - constrainedSize.max.width - child.layoutPosition.x, - constrainedSize.max.height - child.layoutPosition.y - }; - ASSizeRange childConstraint = ASRelativeSizeRangeEqualToRelativeSizeRange(ASRelativeSizeRangeUnconstrained, child.sizeRange) - ? ASSizeRangeMake({0, 0}, autoMaxSize) - : ASRelativeSizeRangeResolve(child.sizeRange, size); + for (id child in children) { + CGPoint layoutPosition = child.layoutPosition; + CGSize autoMaxSize = CGSizeMake(maxConstrainedSize.width - layoutPosition.x, + maxConstrainedSize.height - layoutPosition.y); + + ASRelativeSizeRange childSizeRange = child.sizeRange; + BOOL childIsUnconstrained = ASRelativeSizeRangeEqualToRelativeSizeRange(ASRelativeSizeRangeUnconstrained, childSizeRange); + ASSizeRange childConstraint = childIsUnconstrained ? ASSizeRangeMake({0, 0}, autoMaxSize) + : ASRelativeSizeRangeResolve(childSizeRange, maxConstrainedSize); + ASLayout *sublayout = [child measureWithSizeRange:childConstraint]; - sublayout.position = child.layoutPosition; + sublayout.position = layoutPosition; [sublayouts addObject:sublayout]; } - size.width = constrainedSize.min.width; - for (ASLayout *sublayout in sublayouts) { - size.width = MAX(size.width, sublayout.position.x + sublayout.size.width); - } + CGSize size = CGSizeMake(constrainedSize.min.width, constrainedSize.min.height); - size.height = constrainedSize.min.height; for (ASLayout *sublayout in sublayouts) { - size.height = MAX(size.height, sublayout.position.y + sublayout.size.height); + CGPoint sublayoutPosition = sublayout.position; + CGSize sublayoutSize = sublayout.size; + + size.width = MAX(size.width, sublayoutPosition.x + sublayoutSize.width); + size.height = MAX(size.height, sublayoutPosition.y + sublayoutSize.height); } return [ASLayout layoutWithLayoutableObject:self @@ -75,12 +76,12 @@ - (void)setChild:(id)child forIdentifier:(NSString *)identifier { - ASDisplayNodeAssert(NO, @"ASStackLayoutSpec only supports setChildren"); + ASDisplayNodeAssert(NO, @"ASStaticLayoutSpec only supports setChildren"); } - (id)childForIdentifier:(NSString *)identifier { - ASDisplayNodeAssert(NO, @"ASStackLayoutSpec only supports children"); + ASDisplayNodeAssert(NO, @"ASStaticLayoutSpec only supports children"); return nil; } From c1640c7f59d8d1cec6a18f6ec04bd87563a4078c Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Thu, 24 Dec 2015 18:02:52 -0800 Subject: [PATCH 49/60] Implement getter methods for new table / collection delegate / dataSource. Make ASTableView node-backed. --- AsyncDisplayKit/ASCollectionNode.m | 18 ++++++++++++++++++ AsyncDisplayKit/ASTableNode.m | 24 +++++++++++++++++++++++- AsyncDisplayKit/ASTableView.mm | 23 ++++++++++++----------- 3 files changed, 53 insertions(+), 12 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionNode.m b/AsyncDisplayKit/ASCollectionNode.m index 7cf49fbc..315c3626 100644 --- a/AsyncDisplayKit/ASCollectionNode.m +++ b/AsyncDisplayKit/ASCollectionNode.m @@ -84,6 +84,15 @@ } } +- (id )delegate +{ + if ([self pendingState]) { + return _pendingState.delegate; + } else { + return self.view.asyncDelegate; + } +} + - (void)setDataSource:(id )dataSource { if ([self pendingState]) { @@ -94,6 +103,15 @@ } } +- (id )dataSource +{ + if ([self pendingState]) { + return _pendingState.dataSource; + } else { + return self.view.asyncDataSource; + } +} + - (ASCollectionView *)view { return (ASCollectionView *)[super view]; diff --git a/AsyncDisplayKit/ASTableNode.m b/AsyncDisplayKit/ASTableNode.m index 136c6843..2d9bbc33 100644 --- a/AsyncDisplayKit/ASTableNode.m +++ b/AsyncDisplayKit/ASTableNode.m @@ -20,11 +20,15 @@ @property (nonatomic) _ASTablePendingState *pendingState; @end +@interface ASTableView () +- (instancetype)_initWithFrame:(CGRect)frame style:(UITableViewStyle)style; +@end + @implementation ASTableNode - (instancetype)initWithStyle:(UITableViewStyle)style { - if (self = [super initWithViewBlock:^UIView *{ return [[ASTableView alloc] initWithFrame:CGRectZero style:style]; }]) { + if (self = [super initWithViewBlock:^UIView *{ return [[ASTableView alloc] _initWithFrame:CGRectZero style:style]; }]) { return self; } return nil; @@ -63,6 +67,15 @@ } } +- (id )delegate +{ + if ([self pendingState]) { + return _pendingState.delegate; + } else { + return self.view.asyncDelegate; + } +} + - (void)setDataSource:(id )dataSource { if ([self pendingState]) { @@ -73,6 +86,15 @@ } } +- (id )dataSource +{ + if ([self pendingState]) { + return _pendingState.dataSource; + } else { + return self.view.asyncDataSource; + } +} + - (ASTableView *)view { return (ASTableView *)[super view]; diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index 8d799b5b..162a0fa1 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -8,6 +8,7 @@ #import "ASTableView.h" #import "ASTableViewInternal.h" +#import "ASTableNode.h" #import "ASAssert.h" #import "ASBatchFetching.h" @@ -159,33 +160,33 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; return [self initWithFrame:frame style:style asyncDataFetching:NO]; } +// FIXME: This method is deprecated and will probably be removed in or shortly after 2.0. - (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style asyncDataFetching:(BOOL)asyncDataFetchingEnabled { return [self initWithFrame:frame style:style dataControllerClass:[self.class dataControllerClass] asyncDataFetching:asyncDataFetchingEnabled]; } - (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style dataControllerClass:(Class)dataControllerClass asyncDataFetching:(BOOL)asyncDataFetchingEnabled +{ + ASTableNode *tableNode = [[ASTableNode alloc] initWithStyle:style]; + tableNode.frame = frame; + return tableNode.view; +} + +- (instancetype)_initWithFrame:(CGRect)frame style:(UITableViewStyle)style { if (!(self = [super initWithFrame:frame style:style])) return nil; - - // FIXME: asyncDataFetching is currently unreliable for some use cases. - // https://github.com/facebook/AsyncDisplayKit/issues/385 - asyncDataFetchingEnabled = NO; - [self configureWithDataControllerClass:dataControllerClass asyncDataFetching:asyncDataFetchingEnabled]; + [self configureWithDataControllerClass:[self.class dataControllerClass] asyncDataFetching:NO]; return self; } - (instancetype)initWithCoder:(NSCoder *)aDecoder { - if (!(self = [super initWithCoder:aDecoder])) - return nil; - - [self configureWithDataControllerClass:[self.class dataControllerClass] asyncDataFetching:NO]; - - return self; + NSLog(@"Warning: AsyncDisplayKit is not designed to be used with Interface Builder. Table properties set in IB will be lost."); + return [self initWithFrame:CGRectZero style:UITableViewStylePlain]; } - (void)dealloc From 7ece41ff645b9ee9e132b06cbc2993f3f8f84b5b Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Thu, 24 Dec 2015 21:41:12 -0800 Subject: [PATCH 50/60] Delegate definition tweaks for Table and Collection; ensure Table tests run with ARC enabled. --- AsyncDisplayKit.xcodeproj/project.pbxproj | 2 +- AsyncDisplayKit/ASCollectionView.h | 18 +++++++--------- AsyncDisplayKit/ASPagerNode.h | 21 ++++++++++--------- AsyncDisplayKit/ASPagerNode.m | 10 +++++++-- AsyncDisplayKit/ASTableNode.h | 3 ++- AsyncDisplayKit/ASTableNode.m | 18 +++++++++++++--- AsyncDisplayKit/ASTableView.h | 21 +++++++------------ AsyncDisplayKit/ASTableView.mm | 20 +++++++++++++----- .../ASCollectionViewFlowLayoutInspector.h | 4 ++-- .../ASCollectionViewFlowLayoutInspector.m | 2 +- AsyncDisplayKitTests/ASTableViewTests.m | 14 +++++++------ 11 files changed, 79 insertions(+), 54 deletions(-) diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 136a89cb..02830223 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -242,7 +242,7 @@ 34EFC7771B701D2D00AD841F /* ASStackUnpositionedLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = ACF6ED491B17847A00DA7C62 /* ASStackUnpositionedLayout.h */; }; 34EFC7781B701D3100AD841F /* ASStackUnpositionedLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED4A1B17847A00DA7C62 /* ASStackUnpositionedLayout.mm */; }; 34EFC7791B701D3600AD841F /* ASLayoutSpecUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = ACF6ED451B17847A00DA7C62 /* ASLayoutSpecUtilities.h */; }; - 3C9C128519E616EF00E942A0 /* ASTableViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C9C128419E616EF00E942A0 /* ASTableViewTests.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 3C9C128519E616EF00E942A0 /* ASTableViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C9C128419E616EF00E942A0 /* ASTableViewTests.m */; }; 430E7C8F1B4C23F100697A4C /* ASIndexPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 430E7C8D1B4C23F100697A4C /* ASIndexPath.h */; settings = {ATTRIBUTES = (Public, ); }; }; 430E7C901B4C23F100697A4C /* ASIndexPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 430E7C8D1B4C23F100697A4C /* ASIndexPath.h */; settings = {ATTRIBUTES = (Public, ); }; }; 430E7C911B4C23F100697A4C /* ASIndexPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 430E7C8E1B4C23F100697A4C /* ASIndexPath.m */; }; diff --git a/AsyncDisplayKit/ASCollectionView.h b/AsyncDisplayKit/ASCollectionView.h index b0072e64..f7cd8da0 100644 --- a/AsyncDisplayKit/ASCollectionView.h +++ b/AsyncDisplayKit/ASCollectionView.h @@ -15,8 +15,8 @@ #import @class ASCellNode; -@protocol ASCollectionViewDataSource; -@protocol ASCollectionViewDelegate; +@protocol ASCollectionDataSource; +@protocol ASCollectionDelegate; @protocol ASCollectionViewLayoutInspecting; /** @@ -35,8 +35,8 @@ - (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout; - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout; -@property (nonatomic, weak) id asyncDataSource; -@property (nonatomic, weak) id asyncDelegate; // must not be nil +@property (nonatomic, weak) id asyncDelegate; +@property (nonatomic, weak) id asyncDataSource; /** * Tuning parameters for a range type. @@ -286,9 +286,8 @@ /** * This is a node-based UICollectionViewDataSource. */ -@protocol ASCollectionDataSource -@end -@protocol ASCollectionViewDataSource +#define ASCollectionViewDataSource ASCollectionDataSource +@protocol ASCollectionDataSource /** * Similar to -collectionView:cellForItemAtIndexPath:. @@ -349,9 +348,8 @@ /** * This is a node-based UICollectionViewDelegate. */ -@protocol ASCollectionDelegate -@end -@protocol ASCollectionViewDelegate +#define ASCollectionViewDelegate ASCollectionDelegate +@protocol ASCollectionDelegate @optional diff --git a/AsyncDisplayKit/ASPagerNode.h b/AsyncDisplayKit/ASPagerNode.h index f2f69b61..325eacea 100644 --- a/AsyncDisplayKit/ASPagerNode.h +++ b/AsyncDisplayKit/ASPagerNode.h @@ -8,7 +8,17 @@ #import -@protocol ASPagerNodeDataSource; +@class ASPagerNode; + +@protocol ASPagerNodeDataSource + +// This method replaces -collectionView:numberOfItemsInSection: +- (NSInteger)numberOfPagesInPagerNode:(ASPagerNode *)pagerNode; + +// This method replaces -collectionView:nodeForItemAtIndexPath: +- (ASCellNode *)pagerNode:(ASPagerNode *)pagerNode nodeAtIndex:(NSInteger)index; + +@end @interface ASPagerNode : ASCollectionNode @@ -32,12 +42,3 @@ @end -@protocol ASPagerNodeDataSource - -// This method replaces -collectionView:numberOfItemsInSection: -- (NSInteger)numberOfPagesInPagerNode:(ASPagerNode *)pagerNode; - -// This method replaces -collectionView:nodeForItemAtIndexPath: -- (ASCellNode *)pagerNode:(ASPagerNode *)pagerNode nodeAtIndex:(NSInteger)index; - -@end diff --git a/AsyncDisplayKit/ASPagerNode.m b/AsyncDisplayKit/ASPagerNode.m index dbaaa973..d4537d0a 100644 --- a/AsyncDisplayKit/ASPagerNode.m +++ b/AsyncDisplayKit/ASPagerNode.m @@ -11,7 +11,7 @@ #import -@interface ASPagerNode () { +@interface ASPagerNode () { UICollectionViewFlowLayout *_flowLayout; ASPagerNodeProxy *_proxy; id _pagerDataSource; @@ -20,6 +20,7 @@ @end @implementation ASPagerNode +@dynamic delegate; - (instancetype)init { @@ -50,10 +51,15 @@ if (pagerDataSource != _pagerDataSource) { _pagerDataSource = pagerDataSource; _proxy = pagerDataSource ? [[ASPagerNodeProxy alloc] initWithTarget:pagerDataSource interceptor:self] : nil; - super.dataSource = _proxy; + super.dataSource = (id )_proxy; } } +- (void)proxyTargetHasDeallocated:(ASDelegateProxy *)proxy +{ + [self setDataSource:nil]; +} + - (id )dataSource { return _pagerDataSource; diff --git a/AsyncDisplayKit/ASTableNode.h b/AsyncDisplayKit/ASTableNode.h index d859df67..9ab36470 100644 --- a/AsyncDisplayKit/ASTableNode.h +++ b/AsyncDisplayKit/ASTableNode.h @@ -14,7 +14,8 @@ */ @interface ASTableNode : ASDisplayNode -- (instancetype)initWithStyle:(UITableViewStyle)style NS_DESIGNATED_INITIALIZER; +- (instancetype)init; // UITableViewStylePlain +- (instancetype)initWithStyle:(UITableViewStyle)style; @property (nonatomic, readonly) ASTableView *view; diff --git a/AsyncDisplayKit/ASTableNode.m b/AsyncDisplayKit/ASTableNode.m index 2d9bbc33..f45f742d 100644 --- a/AsyncDisplayKit/ASTableNode.m +++ b/AsyncDisplayKit/ASTableNode.m @@ -21,19 +21,31 @@ @end @interface ASTableView () -- (instancetype)_initWithFrame:(CGRect)frame style:(UITableViewStyle)style; +- (instancetype)_initWithFrame:(CGRect)frame style:(UITableViewStyle)style dataControllerClass:(Class)dataControllerClass; @end @implementation ASTableNode -- (instancetype)initWithStyle:(UITableViewStyle)style +- (instancetype)_initWithStyle:(UITableViewStyle)style dataControllerClass:(Class)dataControllerClass { - if (self = [super initWithViewBlock:^UIView *{ return [[ASTableView alloc] _initWithFrame:CGRectZero style:style]; }]) { + if (self = [super initWithViewBlock:^UIView *{ return [[ASTableView alloc] _initWithFrame:CGRectZero + style:style + dataControllerClass:dataControllerClass]; }]) { return self; } return nil; } +- (instancetype)initWithStyle:(UITableViewStyle)style +{ + return [self _initWithStyle:style dataControllerClass:nil]; +} + +- (instancetype)init +{ + return [self _initWithStyle:UITableViewStylePlain dataControllerClass:nil]; +} + - (void)didLoad { [super didLoad]; diff --git a/AsyncDisplayKit/ASTableView.h b/AsyncDisplayKit/ASTableView.h index f6746874..ae43552d 100644 --- a/AsyncDisplayKit/ASTableView.h +++ b/AsyncDisplayKit/ASTableView.h @@ -7,17 +7,14 @@ */ #import - #import #import #import #import - @class ASCellNode; -@protocol ASTableViewDataSource; -@protocol ASTableViewDelegate; - +@protocol ASTableDataSource; +@protocol ASTableDelegate; /** * Node-based table view. @@ -27,8 +24,8 @@ */ @interface ASTableView : UITableView -@property (nonatomic, weak) id asyncDelegate; // must not be nil -@property (nonatomic, weak) id asyncDataSource; +@property (nonatomic, weak) id asyncDelegate; +@property (nonatomic, weak) id asyncDataSource; /** * Initializer. @@ -280,9 +277,8 @@ /** * This is a node-based UITableViewDataSource. */ -@protocol ASTableDataSource -@end -@protocol ASTableViewDataSource +#define ASTableViewDataSource ASTableDataSource +@protocol ASTableDataSource /** * Similar to -tableView:cellForRowAtIndexPath:. @@ -326,9 +322,8 @@ * Note that -tableView:heightForRowAtIndexPath: has been removed; instead, your custom ASCellNode subclasses are * responsible for deciding their preferred onscreen height in -calculateSizeThatFits:. */ -@protocol ASTableDelegate -@end -@protocol ASTableViewDelegate +#define ASTableViewDelegate ASTableDelegate +@protocol ASTableDelegate @optional diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index 162a0fa1..a5e65178 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -21,6 +21,8 @@ #import "ASLayoutController.h" #import "ASRangeController.h" +#import + static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; //#define LOG(...) NSLog(__VA_ARGS__) @@ -80,6 +82,10 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; #pragma mark - #pragma mark ASTableView +@interface ASTableNode () +- (instancetype)_initWithStyle:(UITableViewStyle)style dataControllerClass:(Class)dataControllerClass; +@end + @interface ASTableView () { ASTableViewProxy *_proxyDataSource; ASTableViewProxy *_proxyDelegate; @@ -168,17 +174,21 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; - (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style dataControllerClass:(Class)dataControllerClass asyncDataFetching:(BOOL)asyncDataFetchingEnabled { - ASTableNode *tableNode = [[ASTableNode alloc] initWithStyle:style]; - tableNode.frame = frame; - return tableNode.view; +// ASTableNode *tableNode = [[ASTableNode alloc] _initWithStyle:style dataControllerClass:dataControllerClass]; +// tableNode.frame = frame; +// return tableNode.view; + return [self _initWithFrame:frame style:style dataControllerClass:dataControllerClass]; } -- (instancetype)_initWithFrame:(CGRect)frame style:(UITableViewStyle)style +- (instancetype)_initWithFrame:(CGRect)frame style:(UITableViewStyle)style dataControllerClass:(Class)dataControllerClass { if (!(self = [super initWithFrame:frame style:style])) return nil; - [self configureWithDataControllerClass:[self.class dataControllerClass] asyncDataFetching:NO]; + if (!dataControllerClass) { + dataControllerClass = [self.class dataControllerClass]; + } + [self configureWithDataControllerClass:dataControllerClass asyncDataFetching:NO]; return self; } diff --git a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.h b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.h index 2890cab8..b2ee2ae8 100644 --- a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.h +++ b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.h @@ -11,7 +11,7 @@ #import @class ASCollectionView; -@protocol ASCollectionViewDelegate; +@protocol ASCollectionDelegate; @protocol ASCollectionViewLayoutInspecting @@ -42,7 +42,7 @@ * * @discussion A great time to update perform selector caches! */ -- (void)didChangeCollectionViewDelegate:(id)delegate; +- (void)didChangeCollectionViewDelegate:(id)delegate; @end diff --git a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m index f6221489..f98afbb9 100644 --- a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m +++ b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m @@ -36,7 +36,7 @@ return self; } -- (void)didChangeCollectionViewDelegate:(id)delegate; +- (void)didChangeCollectionViewDelegate:(id)delegate; { if (delegate == nil) { _delegateImplementsReferenceSizeForHeader = NO; diff --git a/AsyncDisplayKitTests/ASTableViewTests.m b/AsyncDisplayKitTests/ASTableViewTests.m index b4e137bc..a382b6be 100644 --- a/AsyncDisplayKitTests/ASTableViewTests.m +++ b/AsyncDisplayKitTests/ASTableViewTests.m @@ -52,7 +52,6 @@ if (_willDeallocBlock) { _willDeallocBlock(self); } - [super dealloc]; } @end @@ -78,7 +77,6 @@ if (_willDeallocBlock) { _willDeallocBlock(self); } - [super dealloc]; } @end @@ -130,6 +128,7 @@ @implementation ASTableViewTests +// TODO: Convert this to ARC. - (void)DISABLED_testTableViewDoesNotRetainItselfAndDelegate { ASTestTableView *tableView = [[ASTestTableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; @@ -148,11 +147,11 @@ tableView.asyncDataSource = delegate; tableView.asyncDelegate = delegate; - - [delegate release]; + +// [delegate release]; XCTAssertTrue(delegateDidDealloc, @"unexpected delegate lifetime:%@", delegate); - XCTAssertNoThrow([tableView release], @"unexpected exception when deallocating table view:%@", tableView); +// XCTAssertNoThrow([tableView release], @"unexpected exception when deallocating table view:%@", tableView); XCTAssertTrue(tableViewDidDealloc, @"unexpected table view lifetime:%@", tableView); } @@ -399,7 +398,10 @@ style:UITableViewStylePlain asyncDataFetching:YES]; ASTableViewFilledDataSource *dataSource = [ASTableViewFilledDataSource new]; - +#if ! __has_feature(objc_arc) +#error This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). +#endif + tableView.asyncDelegate = dataSource; tableView.asyncDataSource = dataSource; From a0e4484ef7438d94d9a02013a919d5f91d6bb41d Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Thu, 24 Dec 2015 22:27:52 -0800 Subject: [PATCH 51/60] Declare ASPagerNode dataSource property as @dynamic so that it can be a different type than ASCollectionNode. --- AsyncDisplayKit/ASPagerNode.h | 5 +---- AsyncDisplayKit/ASPagerNode.m | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/AsyncDisplayKit/ASPagerNode.h b/AsyncDisplayKit/ASPagerNode.h index 325eacea..2377d1c1 100644 --- a/AsyncDisplayKit/ASPagerNode.h +++ b/AsyncDisplayKit/ASPagerNode.h @@ -9,15 +9,12 @@ #import @class ASPagerNode; - -@protocol ASPagerNodeDataSource - +@protocol ASPagerNodeDataSource // This method replaces -collectionView:numberOfItemsInSection: - (NSInteger)numberOfPagesInPagerNode:(ASPagerNode *)pagerNode; // This method replaces -collectionView:nodeForItemAtIndexPath: - (ASCellNode *)pagerNode:(ASPagerNode *)pagerNode nodeAtIndex:(NSInteger)index; - @end @interface ASPagerNode : ASCollectionNode diff --git a/AsyncDisplayKit/ASPagerNode.m b/AsyncDisplayKit/ASPagerNode.m index d4537d0a..31e7bbad 100644 --- a/AsyncDisplayKit/ASPagerNode.m +++ b/AsyncDisplayKit/ASPagerNode.m @@ -20,7 +20,7 @@ @end @implementation ASPagerNode -@dynamic delegate; +@dynamic delegate, dataSource; - (instancetype)init { From f902b4bdc73185fecd6f7090ff098583e62812d5 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Thu, 24 Dec 2015 22:47:54 -0800 Subject: [PATCH 52/60] Replace property declaration with method overrides for -dataSource. --- AsyncDisplayKit/ASPagerNode.h | 5 +++-- AsyncDisplayKit/ASPagerNode.m | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/AsyncDisplayKit/ASPagerNode.h b/AsyncDisplayKit/ASPagerNode.h index 2377d1c1..746a8055 100644 --- a/AsyncDisplayKit/ASPagerNode.h +++ b/AsyncDisplayKit/ASPagerNode.h @@ -9,7 +9,7 @@ #import @class ASPagerNode; -@protocol ASPagerNodeDataSource +@protocol ASPagerNodeDataSource // This method replaces -collectionView:numberOfItemsInSection: - (NSInteger)numberOfPagesInPagerNode:(ASPagerNode *)pagerNode; @@ -33,7 +33,8 @@ @property (weak, nonatomic) id delegate; // Data Source is required, and uses a different protocol from ASCollectionNode. -@property (weak, nonatomic) id dataSource; +- (void)setDataSource:(id )dataSource; +- (id )dataSource; - (void)scrollToPageAtIndex:(NSInteger)index animated:(BOOL)animated; diff --git a/AsyncDisplayKit/ASPagerNode.m b/AsyncDisplayKit/ASPagerNode.m index 31e7bbad..d4537d0a 100644 --- a/AsyncDisplayKit/ASPagerNode.m +++ b/AsyncDisplayKit/ASPagerNode.m @@ -20,7 +20,7 @@ @end @implementation ASPagerNode -@dynamic delegate, dataSource; +@dynamic delegate; - (instancetype)init { From 4ca97e2f4dd597d0e23747bd78ab75327b927213 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Thu, 24 Dec 2015 23:13:50 -0800 Subject: [PATCH 53/60] Optimize string handling for CALayer gravity & UIView content mode. Finally fix protocol rename. --- AsyncDisplayKit/ASTableView.h | 9 ++++--- .../Private/_ASCoreAnimationExtras.mm | 27 ++++++------------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/AsyncDisplayKit/ASTableView.h b/AsyncDisplayKit/ASTableView.h index ae43552d..410b073f 100644 --- a/AsyncDisplayKit/ASTableView.h +++ b/AsyncDisplayKit/ASTableView.h @@ -277,7 +277,6 @@ /** * This is a node-based UITableViewDataSource. */ -#define ASTableViewDataSource ASTableDataSource @protocol ASTableDataSource /** @@ -315,6 +314,8 @@ @end +@protocol ASTableViewDataSource +@end /** * This is a node-based UITableViewDelegate. @@ -322,7 +323,6 @@ * Note that -tableView:heightForRowAtIndexPath: has been removed; instead, your custom ASCellNode subclasses are * responsible for deciding their preferred onscreen height in -calculateSizeThatFits:. */ -#define ASTableViewDelegate ASTableDelegate @protocol ASTableDelegate @optional @@ -357,4 +357,7 @@ */ - (BOOL)shouldBatchFetchForTableView:(ASTableView *)tableView; -@end \ No newline at end of file +@end + +@protocol ASTableViewDelegate ; +@end diff --git a/AsyncDisplayKit/Private/_ASCoreAnimationExtras.mm b/AsyncDisplayKit/Private/_ASCoreAnimationExtras.mm index 4ff3c52e..a6205e1d 100644 --- a/AsyncDisplayKit/Private/_ASCoreAnimationExtras.mm +++ b/AsyncDisplayKit/Private/_ASCoreAnimationExtras.mm @@ -7,7 +7,7 @@ */ #import "_ASCoreAnimationExtras.h" - +#import "ASEqualityHelpers.h" #import "ASAssert.h" extern void ASDisplayNodeSetupLayerContentsWithResizableImage(CALayer *layer, UIImage *image) @@ -87,7 +87,8 @@ static const struct _UIContentModeStringLUTEntry UIContentModeDescriptionLUT[] = {UIViewContentModeBottomRight, @"bottomRight"}, }; -NSString *ASDisplayNodeNSStringFromUIContentMode(UIViewContentMode contentMode) { +NSString *ASDisplayNodeNSStringFromUIContentMode(UIViewContentMode contentMode) +{ for (int i=0; i< ARRAY_COUNT(UIContentModeDescriptionLUT); i++) { if (UIContentModeDescriptionLUT[i].contentMode == contentMode) { return UIContentModeDescriptionLUT[i].string; @@ -96,16 +97,10 @@ NSString *ASDisplayNodeNSStringFromUIContentMode(UIViewContentMode contentMode) return [NSString stringWithFormat:@"%d", (int)contentMode]; } -UIViewContentMode ASDisplayNodeUIContentModeFromNSString(NSString *string) { - // If you passed one of the constants (this is just an optimization to avoid string comparison) +UIViewContentMode ASDisplayNodeUIContentModeFromNSString(NSString *string) +{ for (int i=0; i < ARRAY_COUNT(UIContentModeDescriptionLUT); i++) { - if (UIContentModeDescriptionLUT[i].string == string) { - return UIContentModeDescriptionLUT[i].contentMode; - } - } - // If you passed something isEqualToString: to one of the constants - for (int i=0; i < ARRAY_COUNT(UIContentModeDescriptionLUT); i++) { - if ([UIContentModeDescriptionLUT[i].string isEqualToString:string]) { + if (ASObjectIsEqual(UIContentModeDescriptionLUT[i].string, string)) { return UIContentModeDescriptionLUT[i].contentMode; } } @@ -126,18 +121,12 @@ NSString *const ASDisplayNodeCAContentsGravityFromUIContentMode(UIViewContentMod UIViewContentMode ASDisplayNodeUIContentModeFromCAContentsGravity(NSString *const contentsGravity) { - // If you passed one of the constants (this is just an optimization to avoid string comparison) for (int i=0; i < ARRAY_COUNT(UIContentModeCAGravityLUT); i++) { - if (UIContentModeCAGravityLUT[i].string == contentsGravity) { - return UIContentModeCAGravityLUT[i].contentMode; - } - } - // If you passed something isEqualToString: to one of the constants - for (int i=0; i < ARRAY_COUNT(UIContentModeCAGravityLUT); i++) { - if ([UIContentModeCAGravityLUT[i].string isEqualToString:contentsGravity]) { + if (ASObjectIsEqual(UIContentModeCAGravityLUT[i].string, contentsGravity)) { return UIContentModeCAGravityLUT[i].contentMode; } } + ASDisplayNodeCAssert(contentsGravity, @"Encountered an unknown contentsGravity \"%@\". Is this a new version of iOS?", contentsGravity); ASDisplayNodeCAssert(!contentsGravity, @"You passed nil to ASDisplayNodeUIContentModeFromCAContentsGravity. We're falling back to resize, but this is probably a bug."); // If asserts disabled, fall back to this From 99fbc97bdaecd2f99009b9734ba0f8f2b665632b Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Fri, 25 Dec 2015 01:36:32 -0800 Subject: [PATCH 54/60] Optimizations for ASTextNode handling of renderer allocation and deallocation. Optimizations for ASDisplayNode handling of bridged property "contentMode", especially for layer-backed nodes. --- AsyncDisplayKit/ASTextNode.mm | 21 ++++++- .../Private/ASDisplayNode+UIViewBridge.mm | 16 +++-- AsyncDisplayKit/Private/ASInternalHelpers.h | 1 + AsyncDisplayKit/Private/ASInternalHelpers.mm | 12 ++++ .../Private/_ASCoreAnimationExtras.mm | 24 +++++++- AsyncDisplayKit/TextKit/ASTextKitRenderer.mm | 58 ++++++++++++++----- 6 files changed, 107 insertions(+), 25 deletions(-) diff --git a/AsyncDisplayKit/ASTextNode.mm b/AsyncDisplayKit/ASTextNode.mm index 3eb5c5ba..fdcfc26b 100644 --- a/AsyncDisplayKit/ASTextNode.mm +++ b/AsyncDisplayKit/ASTextNode.mm @@ -62,6 +62,15 @@ static NSString *ASTextNodeTruncationTokenAttributeName = @"ASTextNodeTruncation - (void)dealloc { CGColorRelease(_backgroundColor); + + // Destruction of the layout managers/containers/text storage is quite + // expensive, and can take some time, so we dispatch onto a bg queue to + // actually dealloc. + __block ASTextKitRenderer *renderer = _renderer; + ASPerformBlockOnBackgroundThread(^{ + renderer = nil; + }); + _renderer = nil; } @end @@ -157,6 +166,8 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; if (_shadowColor != NULL) { CGColorRelease(_shadowColor); } + + [self _invalidateRenderer]; if (_longPressGestureRecognizer) { _longPressGestureRecognizer.delegate = nil; @@ -189,6 +200,8 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; return [[self _renderer] size]; } +// FIXME: Re-evaluate if it is still the right decision to clear the renderer at this stage. +// This code was written before TextKit and when 512MB devices were still the overwhelming majority. - (void)displayDidFinish { [super displayDidFinish]; @@ -263,16 +276,17 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; - (void)_invalidateRenderer { ASDN::MutexLocker l(_rendererLock); + if (_renderer) { // Destruction of the layout managers/containers/text storage is quite // expensive, and can take some time, so we dispatch onto a bg queue to // actually dealloc. __block ASTextKitRenderer *renderer = _renderer; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + ASPerformBlockOnBackgroundThread(^{ renderer = nil; }); + _renderer = nil; } - _renderer = nil; } - (void)_invalidateRendererIfNeeded @@ -320,7 +334,8 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; #pragma mark - Modifying User Text -- (void)setAttributedString:(NSAttributedString *)attributedString { +- (void)setAttributedString:(NSAttributedString *)attributedString +{ if (ASObjectIsEqual(attributedString, _attributedString)) { return; } diff --git a/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm b/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm index 2239cc03..d14c042c 100644 --- a/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm +++ b/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm @@ -446,19 +446,27 @@ { _bridge_prologue; if (__loaded) { - return ASDisplayNodeUIContentModeFromCAContentsGravity(_layer.contentsGravity); + if (_flags.layerBacked) { + return ASDisplayNodeUIContentModeFromCAContentsGravity(_layer.contentsGravity); + } else { + return _view.contentMode; + } } else { return self.pendingViewState.contentMode; } } -- (void)setContentMode:(UIViewContentMode)mode +- (void)setContentMode:(UIViewContentMode)contentMode { _bridge_prologue; if (__loaded) { - _layer.contentsGravity = ASDisplayNodeCAContentsGravityFromUIContentMode(mode); + if (_flags.layerBacked) { + _layer.contentsGravity = ASDisplayNodeCAContentsGravityFromUIContentMode(contentMode); + } else { + _view.contentMode = contentMode; + } } else { - self.pendingViewState.contentMode = mode; + self.pendingViewState.contentMode = contentMode; } } diff --git a/AsyncDisplayKit/Private/ASInternalHelpers.h b/AsyncDisplayKit/Private/ASInternalHelpers.h index 4d1e2ddc..1f173bd9 100644 --- a/AsyncDisplayKit/Private/ASInternalHelpers.h +++ b/AsyncDisplayKit/Private/ASInternalHelpers.h @@ -18,6 +18,7 @@ ASDISPLAYNODE_EXTERN_C_BEGIN BOOL ASSubclassOverridesSelector(Class superclass, Class subclass, SEL selector); BOOL ASSubclassOverridesClassSelector(Class superclass, Class subclass, SEL selector); void ASPerformBlockOnMainThread(void (^block)()); +void ASPerformBlockOnBackgroundThread(void (^block)()); // DISPATCH_QUEUE_PRIORITY_DEFAULT CGFloat ASScreenScale(); diff --git a/AsyncDisplayKit/Private/ASInternalHelpers.mm b/AsyncDisplayKit/Private/ASInternalHelpers.mm index 89a0e817..71ac09d2 100644 --- a/AsyncDisplayKit/Private/ASInternalHelpers.mm +++ b/AsyncDisplayKit/Private/ASInternalHelpers.mm @@ -57,6 +57,18 @@ void ASPerformBlockOnMainThread(void (^block)()) } } +void ASPerformBlockOnBackgroundThread(void (^block)()) +{ + if ([NSThread isMainThread]) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + block(); + }); + } else { + block(); + } +} + + CGFloat ASScreenScale() { static CGFloat _scale; diff --git a/AsyncDisplayKit/Private/_ASCoreAnimationExtras.mm b/AsyncDisplayKit/Private/_ASCoreAnimationExtras.mm index a6205e1d..a0c3b14e 100644 --- a/AsyncDisplayKit/Private/_ASCoreAnimationExtras.mm +++ b/AsyncDisplayKit/Private/_ASCoreAnimationExtras.mm @@ -119,11 +119,31 @@ NSString *const ASDisplayNodeCAContentsGravityFromUIContentMode(UIViewContentMod return nil; } +#define ContentModeCacheSize 10 UIViewContentMode ASDisplayNodeUIContentModeFromCAContentsGravity(NSString *const contentsGravity) { - for (int i=0; i < ARRAY_COUNT(UIContentModeCAGravityLUT); i++) { + static int currentCacheIndex = 0; + static NSMutableArray *cachedStrings = [NSMutableArray arrayWithCapacity:ContentModeCacheSize]; + static UIViewContentMode cachedModes[ContentModeCacheSize] = {}; + + NSInteger foundCacheIndex = [cachedStrings indexOfObjectIdenticalTo:contentsGravity]; + if (foundCacheIndex != NSNotFound && foundCacheIndex < ContentModeCacheSize) { + return cachedModes[foundCacheIndex]; + } + + for (int i = 0; i < ARRAY_COUNT(UIContentModeCAGravityLUT); i++) { if (ASObjectIsEqual(UIContentModeCAGravityLUT[i].string, contentsGravity)) { - return UIContentModeCAGravityLUT[i].contentMode; + UIViewContentMode foundContentMode = UIContentModeCAGravityLUT[i].contentMode; + + if (currentCacheIndex < ContentModeCacheSize) { + // Cache the input value. This is almost always a different pointer than in our LUT and will frequently + // be the same value for an overwhelming majority of inputs. + [cachedStrings addObject:contentsGravity]; + cachedModes[currentCacheIndex] = foundContentMode; + currentCacheIndex++; + } + + return foundContentMode; } } diff --git a/AsyncDisplayKit/TextKit/ASTextKitRenderer.mm b/AsyncDisplayKit/TextKit/ASTextKitRenderer.mm index c00d0061..7630c105 100755 --- a/AsyncDisplayKit/TextKit/ASTextKitRenderer.mm +++ b/AsyncDisplayKit/TextKit/ASTextKitRenderer.mm @@ -32,7 +32,9 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() @implementation ASTextKitRenderer { CGSize _calculatedSize; + BOOL _sizeIsCalculated; } +@synthesize attributes = _attributes, context = _context, shadower = _shadower, truncater = _truncater; #pragma mark - Initialization @@ -42,30 +44,50 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() if (self = [super init]) { _constrainedSize = constrainedSize; _attributes = attributes; + _sizeIsCalculated = NO; + } + return self; +} +- (ASTextKitShadower *)shadower +{ + if (!_shadower) { + ASTextKitAttributes attributes = _attributes; _shadower = [[ASTextKitShadower alloc] initWithShadowOffset:attributes.shadowOffset shadowColor:attributes.shadowColor shadowOpacity:attributes.shadowOpacity shadowRadius:attributes.shadowRadius]; + } + return _shadower; +} +- (ASTextKitTailTruncater *)truncater +{ + if (!_truncater) { + ASTextKitAttributes attributes = _attributes; // We must inset the constrained size by the size of the shadower. - CGSize shadowConstrainedSize = [_shadower insetSizeWithConstrainedSize:_constrainedSize]; + CGSize shadowConstrainedSize = [[self shadower] insetSizeWithConstrainedSize:_constrainedSize]; + _truncater = [[ASTextKitTailTruncater alloc] initWithContext:[self context] + truncationAttributedString:attributes.truncationAttributedString + avoidTailTruncationSet:attributes.avoidTailTruncationSet ?: _defaultAvoidTruncationCharacterSet() + constrainedSize:shadowConstrainedSize]; + } + return _truncater; +} +- (ASTextKitContext *)context +{ + if (!_context) { + ASTextKitAttributes attributes = _attributes; + CGSize shadowConstrainedSize = [[self shadower] insetSizeWithConstrainedSize:_constrainedSize]; _context = [[ASTextKitContext alloc] initWithAttributedString:attributes.attributedString lineBreakMode:attributes.lineBreakMode maximumNumberOfLines:attributes.maximumNumberOfLines exclusionPaths:attributes.exclusionPaths constrainedSize:shadowConstrainedSize layoutManagerFactory:attributes.layoutManagerFactory]; - - _truncater = [[ASTextKitTailTruncater alloc] initWithContext:_context - truncationAttributedString:attributes.truncationAttributedString - avoidTailTruncationSet:attributes.avoidTailTruncationSet ?: _defaultAvoidTruncationCharacterSet() - constrainedSize:shadowConstrainedSize]; - - [self _calculateSize]; } - return self; + return _context; } #pragma mark - Sizing @@ -74,14 +96,14 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() { // Force glyph generation and layout, which may not have happened yet (and isn't triggered by // -usedRectForTextContainer:). - [_context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { + [[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { [layoutManager ensureLayoutForTextContainer:textContainer]; }]; CGRect constrainedRect = {CGPointZero, _constrainedSize}; __block CGRect boundingRect; - [_context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { + [[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { boundingRect = [layoutManager usedRectForTextContainer:textContainer]; }]; @@ -94,6 +116,10 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() - (CGSize)size { + if (!_sizeIsCalculated) { + [self _calculateSize]; + _sizeIsCalculated = YES; + } return _calculatedSize; } @@ -104,13 +130,13 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() // We add an assertion so we can track the rare conditions where a graphics context is not present ASDisplayNodeAssertNotNil(context, @"This is no good without a context."); - CGRect shadowInsetBounds = [_shadower insetRectWithConstrainedRect:bounds]; + CGRect shadowInsetBounds = [[self shadower] insetRectWithConstrainedRect:bounds]; CGContextSaveGState(context); - [_shadower setShadowInContext:context]; + [[self shadower] setShadowInContext:context]; UIGraphicsPushContext(context); - [_context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { + [[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { NSRange glyphRange = [layoutManager glyphRangeForTextContainer:textContainer]; [layoutManager drawBackgroundForGlyphRange:glyphRange atPoint:shadowInsetBounds.origin]; [layoutManager drawGlyphsForGlyphRange:glyphRange atPoint:shadowInsetBounds.origin]; @@ -125,7 +151,7 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() - (NSUInteger)lineCount { __block NSUInteger lineCount = 0; - [_context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { + [[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { for (NSRange lineRange = { 0, 0 }; NSMaxRange(lineRange) < [layoutManager numberOfGlyphs]; lineCount++) { [layoutManager lineFragmentRectForGlyphAtIndex:NSMaxRange(lineRange) effectiveRange:&lineRange]; } @@ -135,7 +161,7 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() - (std::vector)visibleRanges { - return _truncater.visibleRanges; + return [self truncater].visibleRanges; } @end From af74f4a1c26fe65b36fb81c7861ee720f0f06051 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Fri, 25 Dec 2015 14:01:18 -0800 Subject: [PATCH 55/60] Fix the AsyncDisplayKit tests under Xcode 7! Workaround for unfixed Apple bug with @dynamic on CALayer. --- AsyncDisplayKit-Prefix.gcda | Bin 656 -> 656 bytes AsyncDisplayKit.xcodeproj/project.pbxproj | 32 ++++++++------ .../contents.xcworkspacedata | 6 --- AsyncDisplayKit/ASDisplayNode.mm | 17 +++++--- .../_ASAsyncTransactionContainer.m | 40 ++++++++++++++++-- 5 files changed, 69 insertions(+), 26 deletions(-) diff --git a/AsyncDisplayKit-Prefix.gcda b/AsyncDisplayKit-Prefix.gcda index 72e86999c9372666b6b78fd16af20e83deaa4c29..7564c6c3f5969754bf6ba6879ed2be0be65a12ff 100644 GIT binary patch literal 656 zcmYdHNlw=?GB9a6bMz1c0|TQ1kN|-u_8Tg)Ksr9k&)Cp0IJhJ+Iom0*I5j6TFEt>) zII|=(KQA@KC$TcWw8T6)KewQ?B-J&@+sGKI7F`Wc$_Oe2(G*;enjBnGnUfmiZ3wa; zvnn+xF)uw8Xs2UAK@N~&6ao=IEck5i2Yw(OALV0cngn%(TYiyeNop=`a|66B9D^Zt z0rfhjqy&SE69y7YK-{({PDlVq1N|3VVjLfDXjYb*Tmm#R)FM89`ma9&q;>0v!!;ay%$Vh<7){e4r2fK<0}9305FBTf4Rg6gCu_Z!KLru z&b3b~9nkD~{$I*R-v!N}O>=~_e-{$2`N1N}wt_I-wb0p)mlH2LQ&MC^=cMLgM?ozDpLD z$>FfceKxi&bzeEiI`t+8#sJQYC?Ioa>aE7XHh^{1S+{jit?A@M7DhYGsv-ZJr$};S z%zpq9lrD-|dkL>W6h)r5Ree diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 02830223..1cc2d937 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -461,10 +461,10 @@ DE040EF91C2B40AC004692FF /* ASCollectionViewFlowLayoutInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF41BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.h */; settings = {ATTRIBUTES = (Public, ); }; }; DE6EA3221C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */; }; DE6EA3231C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */; }; - DEC447B51C2B9DBC00C8CBD1 /* ASDelegateProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = DEC447B31C2B9DBC00C8CBD1 /* ASDelegateProxy.h */; }; - DEC447B61C2B9DBC00C8CBD1 /* ASDelegateProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = DEC447B31C2B9DBC00C8CBD1 /* ASDelegateProxy.h */; }; - DEC447B71C2B9DBC00C8CBD1 /* ASDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = DEC447B41C2B9DBC00C8CBD1 /* ASDelegateProxy.m */; }; - DEC447B81C2B9DBC00C8CBD1 /* ASDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = DEC447B41C2B9DBC00C8CBD1 /* ASDelegateProxy.m */; }; + DE8BEAC11C2DF3FC00D57C12 /* ASDelegateProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = DE8BEABF1C2DF3FC00D57C12 /* ASDelegateProxy.h */; }; + DE8BEAC21C2DF3FC00D57C12 /* ASDelegateProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = DE8BEABF1C2DF3FC00D57C12 /* ASDelegateProxy.h */; }; + DE8BEAC31C2DF3FC00D57C12 /* ASDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = DE8BEAC01C2DF3FC00D57C12 /* ASDelegateProxy.m */; }; + DE8BEAC41C2DF3FC00D57C12 /* ASDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = DE8BEAC01C2DF3FC00D57C12 /* ASDelegateProxy.m */; }; DECBD6E71BE56E1900CF4905 /* ASButtonNode.h in Headers */ = {isa = PBXBuildFile; fileRef = DECBD6E51BE56E1900CF4905 /* ASButtonNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; DECBD6E81BE56E1900CF4905 /* ASButtonNode.h in Headers */ = {isa = PBXBuildFile; fileRef = DECBD6E51BE56E1900CF4905 /* ASButtonNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; DECBD6E91BE56E1900CF4905 /* ASButtonNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = DECBD6E61BE56E1900CF4905 /* ASButtonNode.mm */; }; @@ -758,8 +758,8 @@ D785F6601A74327E00291744 /* ASScrollNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASScrollNode.h; sourceTree = ""; }; D785F6611A74327E00291744 /* ASScrollNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASScrollNode.m; sourceTree = ""; }; DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASDisplayNode+FrameworkPrivate.h"; sourceTree = ""; }; - DEC447B31C2B9DBC00C8CBD1 /* ASDelegateProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDelegateProxy.h; sourceTree = ""; }; - DEC447B41C2B9DBC00C8CBD1 /* ASDelegateProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDelegateProxy.m; sourceTree = ""; }; + DE8BEABF1C2DF3FC00D57C12 /* ASDelegateProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDelegateProxy.h; sourceTree = ""; }; + DE8BEAC01C2DF3FC00D57C12 /* ASDelegateProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDelegateProxy.m; sourceTree = ""; }; DECBD6E51BE56E1900CF4905 /* ASButtonNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASButtonNode.h; sourceTree = ""; }; DECBD6E61BE56E1900CF4905 /* ASButtonNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASButtonNode.mm; sourceTree = ""; }; EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AsyncDisplayKitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1155,8 +1155,8 @@ 25B171EA1C12242700508A7A /* Data Controller */ = { isa = PBXGroup; children = ( - DEC447B31C2B9DBC00C8CBD1 /* ASDelegateProxy.h */, - DEC447B41C2B9DBC00C8CBD1 /* ASDelegateProxy.m */, + DE8BEABF1C2DF3FC00D57C12 /* ASDelegateProxy.h */, + DE8BEAC01C2DF3FC00D57C12 /* ASDelegateProxy.m */, 251B8EF21BBB3D690087C538 /* ASCollectionDataController.h */, 251B8EF31BBB3D690087C538 /* ASCollectionDataController.mm */, 464052191A3F83C40061C0BA /* ASDataController.h */, @@ -1272,7 +1272,7 @@ 18C2ED7E1B9B7DE800F627B3 /* ASCollectionNode.h in Headers */, 257754C01BEE458E00737CA5 /* ASTextNodeWordKerner.h in Headers */, AC3C4A511A1139C100143C57 /* ASCollectionView.h in Headers */, - DEC447B51C2B9DBC00C8CBD1 /* ASDelegateProxy.h in Headers */, + DE8BEAC11C2DF3FC00D57C12 /* ASDelegateProxy.h in Headers */, 205F0E1D1B373A2C007741D0 /* ASCollectionViewLayoutController.h in Headers */, AC3C4A541A113EEC00143C57 /* ASCollectionViewProtocols.h in Headers */, 058D0A49195D05CB00B7D73C /* ASControlNode+Subclasses.h in Headers */, @@ -1441,7 +1441,7 @@ 34EFC7791B701D3600AD841F /* ASLayoutSpecUtilities.h in Headers */, B350625C1B010F070018CF92 /* ASLog.h in Headers */, 0442850E1BAA64EC00D16268 /* ASMultidimensionalArrayUtils.h in Headers */, - DEC447B61C2B9DBC00C8CBD1 /* ASDelegateProxy.h in Headers */, + DE8BEAC21C2DF3FC00D57C12 /* ASDelegateProxy.h in Headers */, B35062041B010EFD0018CF92 /* ASMultiplexImageNode.h in Headers */, DECBD6E81BE56E1900CF4905 /* ASButtonNode.h in Headers */, B35062241B010EFD0018CF92 /* ASMutableAttributedStringBuilder.h in Headers */, @@ -1697,7 +1697,7 @@ 0549634A1A1EA066000F8E56 /* ASBasicImageDownloader.mm in Sources */, 299DA1AA1A828D2900162D41 /* ASBatchContext.mm in Sources */, AC6456091B0A335000CF11B8 /* ASCellNode.m in Sources */, - DEC447B71C2B9DBC00C8CBD1 /* ASDelegateProxy.m in Sources */, + DE8BEAC31C2DF3FC00D57C12 /* ASDelegateProxy.m in Sources */, ACF6ED1D1B17843500DA7C62 /* ASCenterLayoutSpec.mm in Sources */, 18C2ED801B9B7DE800F627B3 /* ASCollectionNode.m in Sources */, 92DD2FE41BF4B97E0074C9DD /* ASMapNode.mm in Sources */, @@ -1827,7 +1827,7 @@ 509E68621B3AEDA5009B9150 /* ASAbstractLayoutController.mm in Sources */, 254C6B861BF94F8A003EC431 /* ASTextKitContext.mm in Sources */, 34EFC7621B701CA400AD841F /* ASBackgroundLayoutSpec.mm in Sources */, - DEC447B81C2B9DBC00C8CBD1 /* ASDelegateProxy.m in Sources */, + DE8BEAC41C2DF3FC00D57C12 /* ASDelegateProxy.m in Sources */, B35062141B010EFD0018CF92 /* ASBasicImageDownloader.mm in Sources */, B35062161B010EFD0018CF92 /* ASBatchContext.mm in Sources */, AC47D9421B3B891B00AAEE9D /* ASCellNode.m in Sources */, @@ -1934,6 +1934,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", @@ -1954,6 +1955,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; INFOPLIST_FILE = AsyncDisplayKitTestHost/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 7.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -2041,6 +2043,7 @@ APPLICATION_EXTENSION_API_ONLY = YES; DSTROOT = /tmp/AsyncDisplayKit.dst; GCC_INPUT_FILETYPE = automatic; + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "AsyncDisplayKit/AsyncDisplayKit-Prefix.pch"; GCC_TREAT_WARNINGS_AS_ERRORS = YES; @@ -2059,6 +2062,7 @@ APPLICATION_EXTENSION_API_ONLY = YES; DSTROOT = /tmp/AsyncDisplayKit.dst; GCC_INPUT_FILETYPE = automatic; + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "AsyncDisplayKit/AsyncDisplayKit-Prefix.pch"; GCC_TREAT_WARNINGS_AS_ERRORS = YES; @@ -2081,6 +2085,7 @@ "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)", ); + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "AsyncDisplayKit/AsyncDisplayKit-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -2108,6 +2113,7 @@ "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)", ); + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "AsyncDisplayKit/AsyncDisplayKit-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -2136,6 +2142,7 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -2168,6 +2175,7 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = "$(SRCROOT)/AsyncDisplayKit-iOS/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; diff --git a/AsyncDisplayKit.xcworkspace/contents.xcworkspacedata b/AsyncDisplayKit.xcworkspace/contents.xcworkspacedata index 5f740017..574f0ec1 100644 --- a/AsyncDisplayKit.xcworkspace/contents.xcworkspacedata +++ b/AsyncDisplayKit.xcworkspace/contents.xcworkspacedata @@ -1,12 +1,6 @@ - - - - diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 5540c7c8..52f38cda 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -2317,7 +2317,6 @@ static void _recursivelySetDisplaySuspended(ASDisplayNode *node, CALayer *layer, static const char *ASDisplayNodeAssociatedNodeKey = "ASAssociatedNode"; @implementation UIView (ASDisplayNodeInternal) -@dynamic asyncdisplaykit_node; - (void)setAsyncdisplaykit_node:(ASDisplayNode *)node { @@ -2326,16 +2325,24 @@ static const char *ASDisplayNodeAssociatedNodeKey = "ASAssociatedNode"; - (ASDisplayNode *)asyncdisplaykit_node { - ASDisplayNode *node = objc_getAssociatedObject(self, ASDisplayNodeAssociatedNodeKey); - return node; + return objc_getAssociatedObject(self, ASDisplayNodeAssociatedNodeKey); } @end @implementation CALayer (ASDisplayNodeInternal) -@dynamic asyncdisplaykit_node; -@end +- (void)setAsyncdisplaykit_node:(ASDisplayNode *)node +{ + objc_setAssociatedObject(self, ASDisplayNodeAssociatedNodeKey, node, OBJC_ASSOCIATION_ASSIGN); // Weak reference to avoid cycle, since the node retains the layer. +} + +- (ASDisplayNode *)asyncdisplaykit_node +{ + return objc_getAssociatedObject(self, ASDisplayNodeAssociatedNodeKey); +} + +@end @implementation UIView (AsyncDisplayKit) diff --git a/AsyncDisplayKit/Details/Transactions/_ASAsyncTransactionContainer.m b/AsyncDisplayKit/Details/Transactions/_ASAsyncTransactionContainer.m index cbf26a6d..fd2d02a6 100644 --- a/AsyncDisplayKit/Details/Transactions/_ASAsyncTransactionContainer.m +++ b/AsyncDisplayKit/Details/Transactions/_ASAsyncTransactionContainer.m @@ -10,19 +10,53 @@ #import "_ASAsyncTransaction.h" #import "_ASAsyncTransactionGroup.h" +#import + +static const char *ASDisplayNodeAssociatedTransactionsKey = "ASAssociatedTransactions"; +static const char *ASDisplayNodeAssociatedCurrentTransactionKey = "ASAssociatedCurrentTransaction"; @implementation CALayer (ASAsyncTransactionContainerTransactions) -@dynamic asyncdisplaykit_asyncLayerTransactions; -@dynamic asyncdisplaykit_currentAsyncLayerTransaction; + +- (_ASAsyncTransaction *)asyncdisplaykit_currentAsyncLayerTransaction +{ + return objc_getAssociatedObject(self, ASDisplayNodeAssociatedCurrentTransactionKey); +} + +- (void)asyncdisplaykit_setCurrentAsyncLayerTransaction:(_ASAsyncTransaction *)transaction +{ + objc_setAssociatedObject(self, ASDisplayNodeAssociatedCurrentTransactionKey, transaction, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (NSHashTable *)asyncdisplaykit_asyncLayerTransactions +{ + return objc_getAssociatedObject(self, ASDisplayNodeAssociatedTransactionsKey); +} + +- (void)asyncdisplaykit_setAsyncLayerTransactions:(NSHashTable *)transactions +{ + objc_setAssociatedObject(self, ASDisplayNodeAssociatedTransactionsKey, transactions, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} // No-ops in the base class. Mostly exposed for testing. - (void)asyncdisplaykit_asyncTransactionContainerWillBeginTransaction:(_ASAsyncTransaction *)transaction {} - (void)asyncdisplaykit_asyncTransactionContainerDidCompleteTransaction:(_ASAsyncTransaction *)transaction {} @end +static const char *ASAsyncTransactionIsContainerKey = "ASTransactionIsContainer"; + @implementation CALayer (ASDisplayNodeAsyncTransactionContainer) -@dynamic asyncdisplaykit_asyncTransactionContainer; +- (BOOL)asyncdisplaykit_isAsyncTransactionContainer +{ + CFBooleanRef isContainerBool = (__bridge CFBooleanRef)objc_getAssociatedObject(self, ASAsyncTransactionIsContainerKey); + BOOL isContainer = (isContainerBool == kCFBooleanTrue); + return isContainer; +} + +- (void)asyncdisplaykit_setAsyncTransactionContainer:(BOOL)isContainer +{ + objc_setAssociatedObject(self, ASAsyncTransactionIsContainerKey, (id)(isContainer ? kCFBooleanTrue : kCFBooleanFalse), OBJC_ASSOCIATION_ASSIGN); +} - (ASAsyncTransactionContainerState)asyncdisplaykit_asyncTransactionContainerState { From c6fa897dc2826bad6f32c5ecc6ad1f0c5afc84df Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Fri, 25 Dec 2015 15:35:52 -0800 Subject: [PATCH 56/60] Add nullability annotations to newer APIs that lacked it from the original PR. --- AsyncDisplayKit-Prefix.gcda | Bin 656 -> 656 bytes AsyncDisplayKit/ASDisplayNode.h | 2 +- AsyncDisplayKit/ASTableView.h | 8 +++----- AsyncDisplayKit/ASViewController.m | 6 ++++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/AsyncDisplayKit-Prefix.gcda b/AsyncDisplayKit-Prefix.gcda index 7564c6c3f5969754bf6ba6879ed2be0be65a12ff..83c74d3faa7677539da52471bcce34199dab999b 100644 GIT binary patch literal 656 zcmb`E%}T^D6on`Ltwix3T)EbbGo!;e;G#HP3`miQZWIYIy-tgv8IrWncknG-&s(_h z8Ql9E-n4<4ML`7v=iW3V-#v%&SWJ#Pr)RBtkxjpGZ5?&;5Kx-&sY#T*1!J$cfg>h) zsd5`+@h~-0{D@QxgGc|AU?*Fy_=64X%^VFP*Cs7MmeTZgo~F{mUIy}o<|r%7Q+JDb{T8;3aFr1 zn6YSLa?=lJoi?KEf=j6cw@Qy_mxWwUT0E2ztl;LYWB=M}e&@B#!rWKZ}{ uMt6Po7d}pk5J&d0tfG3e+3U`K@Xv(=uB!|#tebI&WexR7-oFlhnDGsPqqmj- literal 656 zcmYdHNlw=?GB9a6bMz1c0|TQ1kN|-u_8Tg)Ksr9k&)Cp0IJhJ+Iom0*I5j6TFEt>) zII|=(KQA@KC$TcWw8T6)KewQ?B-J&@+sGKI7F`Wc$_Oe2(G*;enjBnGnUfmiZ3wa; zvnn+xF)uw8Xs2UAK@N~&6ao=IEck5i2Yw(OALV0cngn%(TYiyeNop=`a|66B9D^Zt z0rfhjqy&SE69y7YK-{({PDlVq1N|3VVjLfDXjYb*Tmm#R)FM89`ma9&q;>0v!!;ay%$Vh<7){e4r2fK<0}9305FBTf4Rg6gCu_Z; +@protocol ASTableViewDelegate @end ->>>>>>> master + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASViewController.m b/AsyncDisplayKit/ASViewController.m index 519ac4b3..96797855 100644 --- a/AsyncDisplayKit/ASViewController.m +++ b/AsyncDisplayKit/ASViewController.m @@ -18,12 +18,14 @@ - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { - return [self initWithNode:nil]; + ASDisplayNodeAssert(NO, @"ASViewController requires using -initWithNode:"); + return [self initWithNode:[[ASDisplayNode alloc] init]]; } - (instancetype)initWithCoder:(NSCoder *)aDecoder { - return [self initWithNode:nil]; + ASDisplayNodeAssert(NO, @"ASViewController requires using -initWithNode:"); + return [self initWithNode:[[ASDisplayNode alloc] init]]; } - (instancetype)initWithNode:(ASDisplayNode *)node From 89f9fc551f4c05eda9c1581af547373e31dfdf62 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Fri, 25 Dec 2015 15:59:46 -0800 Subject: [PATCH 57/60] Update Travis build server to use Xcode 7.2. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 520f2f76..fd3259eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: xcode7 +osx_image: xcode7.2 before_install: - brew update - brew reinstall xctool From a2cf2a88e63a56ccf77b0b236ec3fbfd35aa4d38 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Fri, 25 Dec 2015 19:22:00 -0800 Subject: [PATCH 58/60] Overhaul header files / includes to eliminate circular references that Xcode 7 is angry about. --- AsyncDisplayKit/ASButtonNode.h | 3 ++- AsyncDisplayKit/ASButtonNode.mm | 5 +++-- AsyncDisplayKit/ASCollectionView.mm | 1 - AsyncDisplayKit/ASControlNode+Subclasses.h | 2 +- AsyncDisplayKit/ASDisplayNode.mm | 4 +++- AsyncDisplayKit/ASMapNode.h | 2 +- AsyncDisplayKit/ASMapNode.mm | 2 ++ AsyncDisplayKit/ASPagerNode.m | 3 +-- AsyncDisplayKit/ASTableNode.h | 2 +- AsyncDisplayKit/ASTableNode.m | 2 ++ AsyncDisplayKit/ASTableView.mm | 2 -- AsyncDisplayKit/ASTableViewInternal.h | 2 +- AsyncDisplayKit/AsyncDisplayKit.h | 2 -- .../Details/ASCollectionViewFlowLayoutInspector.m | 1 - AsyncDisplayKit/Details/ASDataController+Subclasses.h | 7 ++++++- AsyncDisplayKit/Details/ASDataController.h | 10 +++++++--- AsyncDisplayKit/Details/ASRangeController.h | 1 - AsyncDisplayKit/Details/CGRect+ASConvenience.h | 1 + AsyncDisplayKit/Layout/ASLayoutOptions.h | 3 ++- AsyncDisplayKit/Layout/ASLayoutSpec.mm | 3 +-- AsyncDisplayKit/Layout/ASStackLayoutSpec.mm | 3 --- AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm | 1 - .../Private/ASBasicImageDownloaderInternal.h | 3 --- AsyncDisplayKit/Private/ASDisplayNode+AsyncDisplay.mm | 4 ++++ .../Private/ASDisplayNode+FrameworkPrivate.h | 3 +-- AsyncDisplayKit/Private/ASDisplayNodeInternal.h | 6 ++++-- AsyncDisplayKit/Private/ASStackPositionedLayout.h | 1 - AsyncDisplayKit/Private/_ASHierarchyChangeSet.h | 4 +++- 28 files changed, 46 insertions(+), 37 deletions(-) diff --git a/AsyncDisplayKit/ASButtonNode.h b/AsyncDisplayKit/ASButtonNode.h index 57b7caf1..81564962 100644 --- a/AsyncDisplayKit/ASButtonNode.h +++ b/AsyncDisplayKit/ASButtonNode.h @@ -6,7 +6,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import +#import +#import typedef enum : NSUInteger { ASButtonStateNormal, diff --git a/AsyncDisplayKit/ASButtonNode.mm b/AsyncDisplayKit/ASButtonNode.mm index 196216a6..0d400441 100644 --- a/AsyncDisplayKit/ASButtonNode.mm +++ b/AsyncDisplayKit/ASButtonNode.mm @@ -7,8 +7,9 @@ */ #import "ASButtonNode.h" - -#import +#import "ASStackLayoutSpec.h" +#import "ASThread.h" +#import "ASDisplayNode+Subclasses.h" @interface ASButtonNode () { diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index c044919b..8686ce6c 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -9,7 +9,6 @@ #import "ASAssert.h" #import "ASBatchFetching.h" #import "ASDelegateProxy.h" -#import "ASCollectionView.h" #import "ASCollectionNode.h" #import "ASCollectionDataController.h" #import "ASCollectionViewLayoutController.h" diff --git a/AsyncDisplayKit/ASControlNode+Subclasses.h b/AsyncDisplayKit/ASControlNode+Subclasses.h index 085eb9bb..107de031 100644 --- a/AsyncDisplayKit/ASControlNode+Subclasses.h +++ b/AsyncDisplayKit/ASControlNode+Subclasses.h @@ -6,7 +6,7 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import +#import "ASControlNode.h" NS_ASSUME_NONNULL_BEGIN diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 52f38cda..19c972f7 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -6,7 +6,6 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import "ASDisplayNode.h" #import "ASDisplayNodeInternal.h" #import "ASDisplayNode+Subclasses.h" #import "ASDisplayNode+FrameworkPrivate.h" @@ -49,6 +48,9 @@ #define TIME_SCOPED(outVar) #endif +@interface ASDisplayNode () <_ASDisplayLayerDelegate> +@end + @implementation ASDisplayNode // these dynamic properties all defined in ASLayoutOptionsPrivate.m diff --git a/AsyncDisplayKit/ASMapNode.h b/AsyncDisplayKit/ASMapNode.h index e0083506..0a8b0ebb 100644 --- a/AsyncDisplayKit/ASMapNode.h +++ b/AsyncDisplayKit/ASMapNode.h @@ -6,7 +6,7 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import +#import #import NS_ASSUME_NONNULL_BEGIN diff --git a/AsyncDisplayKit/ASMapNode.mm b/AsyncDisplayKit/ASMapNode.mm index 480360a1..ce4f3fc8 100644 --- a/AsyncDisplayKit/ASMapNode.mm +++ b/AsyncDisplayKit/ASMapNode.mm @@ -7,6 +7,8 @@ */ #import "ASMapNode.h" +#import +#import #import #import #import diff --git a/AsyncDisplayKit/ASPagerNode.m b/AsyncDisplayKit/ASPagerNode.m index d4537d0a..b8a52f73 100644 --- a/AsyncDisplayKit/ASPagerNode.m +++ b/AsyncDisplayKit/ASPagerNode.m @@ -8,8 +8,7 @@ #import "ASPagerNode.h" #import "ASDelegateProxy.h" - -#import +#import "ASDisplayNode+Subclasses.h" @interface ASPagerNode () { UICollectionViewFlowLayout *_flowLayout; diff --git a/AsyncDisplayKit/ASTableNode.h b/AsyncDisplayKit/ASTableNode.h index 9ab36470..13d5c88f 100644 --- a/AsyncDisplayKit/ASTableNode.h +++ b/AsyncDisplayKit/ASTableNode.h @@ -6,7 +6,7 @@ // Copyright © 2015 Facebook. All rights reserved. // -#import +#import /** * ASTableNode is a node based class that wraps an ASTableView. It can be used diff --git a/AsyncDisplayKit/ASTableNode.m b/AsyncDisplayKit/ASTableNode.m index f45f742d..2917b73c 100644 --- a/AsyncDisplayKit/ASTableNode.m +++ b/AsyncDisplayKit/ASTableNode.m @@ -6,7 +6,9 @@ // Copyright © 2015 Facebook. All rights reserved. // +#import "ASFlowLayoutController.h" #import "ASTableNode.h" +#import "ASDisplayNode+Subclasses.h" @interface _ASTablePendingState : NSObject @property (weak, nonatomic) id delegate; diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index a5e65178..b2f6457f 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -6,9 +6,7 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import "ASTableView.h" #import "ASTableViewInternal.h" -#import "ASTableNode.h" #import "ASAssert.h" #import "ASBatchFetching.h" diff --git a/AsyncDisplayKit/ASTableViewInternal.h b/AsyncDisplayKit/ASTableViewInternal.h index af940837..8d43beaf 100644 --- a/AsyncDisplayKit/ASTableViewInternal.h +++ b/AsyncDisplayKit/ASTableViewInternal.h @@ -6,7 +6,7 @@ // Copyright (c) 2015 Facebook. All rights reserved. // -#import "ASTableView.h" +#import "ASTableNode.h" @class ASDataController; diff --git a/AsyncDisplayKit/AsyncDisplayKit.h b/AsyncDisplayKit/AsyncDisplayKit.h index 0cb9a32f..b854d756 100644 --- a/AsyncDisplayKit/AsyncDisplayKit.h +++ b/AsyncDisplayKit/AsyncDisplayKit.h @@ -52,8 +52,6 @@ #import #import #import -#import -#import #import #import #import diff --git a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m index f98afbb9..61687308 100644 --- a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m +++ b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m @@ -9,7 +9,6 @@ #import #import "ASCollectionViewFlowLayoutInspector.h" - #import "ASCollectionView.h" #import "ASAssert.h" #import "ASEqualityHelpers.h" diff --git a/AsyncDisplayKit/Details/ASDataController+Subclasses.h b/AsyncDisplayKit/Details/ASDataController+Subclasses.h index 23c28e9a..32d78791 100644 --- a/AsyncDisplayKit/Details/ASDataController+Subclasses.h +++ b/AsyncDisplayKit/Details/ASDataController+Subclasses.h @@ -6,7 +6,10 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import "ASDataController.h" +#ifndef ASDataControllerSubclasses_Included +#define ASDataControllerSubclasses_Included + +//#import "ASDataController.h" @interface ASDataController (Subclasses) @@ -157,3 +160,5 @@ - (void)willMoveSection:(NSInteger)section toSection:(NSInteger)newSection; @end + +#endif diff --git a/AsyncDisplayKit/Details/ASDataController.h b/AsyncDisplayKit/Details/ASDataController.h index 8b27d7e2..5710b22b 100644 --- a/AsyncDisplayKit/Details/ASDataController.h +++ b/AsyncDisplayKit/Details/ASDataController.h @@ -6,19 +6,21 @@ * of patent rights can be found in the PATENTS file in the same directory. */ +#ifndef ASDataController_Included +#define ASDataController_Included + #import #import #import -#import "ASFlowLayoutController.h" +#import NS_ASSUME_NONNULL_BEGIN @class ASCellNode; @class ASDataController; -FOUNDATION_EXPORT NSString * const ASDataControllerRowNodeKind; - typedef NSUInteger ASDataControllerAnimationOptions; +FOUNDATION_EXPORT NSString * const ASDataControllerRowNodeKind; /** Data source for data controller @@ -192,3 +194,5 @@ typedef NSUInteger ASDataControllerAnimationOptions; @end NS_ASSUME_NONNULL_END + +#endif diff --git a/AsyncDisplayKit/Details/ASRangeController.h b/AsyncDisplayKit/Details/ASRangeController.h index 6e35cd41..3e8e00a5 100644 --- a/AsyncDisplayKit/Details/ASRangeController.h +++ b/AsyncDisplayKit/Details/ASRangeController.h @@ -10,7 +10,6 @@ #import #import -#import #import NS_ASSUME_NONNULL_BEGIN diff --git a/AsyncDisplayKit/Details/CGRect+ASConvenience.h b/AsyncDisplayKit/Details/CGRect+ASConvenience.h index 9743eb49..a60b46be 100644 --- a/AsyncDisplayKit/Details/CGRect+ASConvenience.h +++ b/AsyncDisplayKit/Details/CGRect+ASConvenience.h @@ -6,6 +6,7 @@ * of patent rights can be found in the PATENTS file in the same directory. */ +#import #import #import "ASBaseDefines.h" diff --git a/AsyncDisplayKit/Layout/ASLayoutOptions.h b/AsyncDisplayKit/Layout/ASLayoutOptions.h index bda890cc..88036d1b 100644 --- a/AsyncDisplayKit/Layout/ASLayoutOptions.h +++ b/AsyncDisplayKit/Layout/ASLayoutOptions.h @@ -9,7 +9,8 @@ */ #import -#import +#import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.mm b/AsyncDisplayKit/Layout/ASLayoutSpec.mm index 376c606e..dfe40084 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.mm @@ -8,7 +8,7 @@ * */ -#import "ASLayoutSpec.h" +#import "ASLayoutOptionsPrivate.h" #import "ASAssert.h" #import "ASBaseDefines.h" @@ -16,7 +16,6 @@ #import "ASInternalHelpers.h" #import "ASLayout.h" #import "ASLayoutOptions.h" -#import "ASLayoutOptionsPrivate.h" #import "ASThread.h" #import diff --git a/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm b/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm index facbbb1e..76539bf5 100644 --- a/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm @@ -8,8 +8,6 @@ * */ -#import "ASStackLayoutSpec.h" - #import #import @@ -19,7 +17,6 @@ #import "ASLayoutSpecUtilities.h" #import "ASStackBaselinePositionedLayout.h" #import "ASStackLayoutSpecUtilities.h" -#import "ASStackPositionedLayout.h" #import "ASStackUnpositionedLayout.h" #import "ASThread.h" diff --git a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm index ae957559..2d0edba4 100644 --- a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm @@ -14,7 +14,6 @@ #import "ASLayoutOptions.h" #import "ASInternalHelpers.h" #import "ASLayout.h" -#import "ASStaticLayoutable.h" @implementation ASStaticLayoutSpec diff --git a/AsyncDisplayKit/Private/ASBasicImageDownloaderInternal.h b/AsyncDisplayKit/Private/ASBasicImageDownloaderInternal.h index b6751a5d..210fe397 100644 --- a/AsyncDisplayKit/Private/ASBasicImageDownloaderInternal.h +++ b/AsyncDisplayKit/Private/ASBasicImageDownloaderInternal.h @@ -6,9 +6,6 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import "ASThread.h" - - @interface ASBasicImageDownloaderContext : NSObject + (ASBasicImageDownloaderContext *)contextForURL:(NSURL *)URL; diff --git a/AsyncDisplayKit/Private/ASDisplayNode+AsyncDisplay.mm b/AsyncDisplayKit/Private/ASDisplayNode+AsyncDisplay.mm index b0cabb67..2566d0e2 100644 --- a/AsyncDisplayKit/Private/ASDisplayNode+AsyncDisplay.mm +++ b/AsyncDisplayKit/Private/ASDisplayNode+AsyncDisplay.mm @@ -8,10 +8,14 @@ #import "_ASCoreAnimationExtras.h" #import "_ASAsyncTransaction.h" +#import "_ASDisplayLayer.h" #import "ASAssert.h" #import "ASDisplayNodeInternal.h" #import "ASDisplayNode+FrameworkPrivate.h" +@interface ASDisplayNode () <_ASDisplayLayerDelegate> +@end + @implementation ASDisplayNode (AsyncDisplay) /** diff --git a/AsyncDisplayKit/Private/ASDisplayNode+FrameworkPrivate.h b/AsyncDisplayKit/Private/ASDisplayNode+FrameworkPrivate.h index 126cd869..0c016d00 100644 --- a/AsyncDisplayKit/Private/ASDisplayNode+FrameworkPrivate.h +++ b/AsyncDisplayKit/Private/ASDisplayNode+FrameworkPrivate.h @@ -11,7 +11,6 @@ // These methods must never be called or overridden by other classes. // -#import "_ASDisplayLayer.h" #import "_AS-objc-internal.h" #import "ASDisplayNodeExtraIvars.h" #import "ASDisplayNode.h" @@ -52,7 +51,7 @@ typedef NS_OPTIONS(NSUInteger, ASHierarchyState) ASHierarchyStateTransitioningSupernodes = 1 << 2 }; -@interface ASDisplayNode () <_ASDisplayLayerDelegate> +@interface ASDisplayNode () { @protected ASInterfaceState _interfaceState; diff --git a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h index c4c9d2ab..ca5a7ee1 100644 --- a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h +++ b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h @@ -11,7 +11,6 @@ // These methods must never be called or overridden by other classes. // -#import "_ASDisplayLayer.h" #import "_AS-objc-internal.h" #import "ASDisplayNodeExtraIvars.h" #import "ASDisplayNode.h" @@ -19,6 +18,9 @@ #import "ASThread.h" #import "ASLayoutOptions.h" +@protocol _ASDisplayLayerDelegate; +@class _ASDisplayLayer; + BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector); void ASDisplayNodeRespectThreadAffinityOfNode(ASDisplayNode *node, void (^block)()); @@ -39,7 +41,7 @@ typedef NS_OPTIONS(NSUInteger, ASDisplayNodeMethodOverrides) #define TIME_DISPLAYNODE_OPS (DEBUG || PROFILE) -@interface ASDisplayNode () <_ASDisplayLayerDelegate> +@interface ASDisplayNode () { @protected // Protects access to _view, _layer, _pendingViewState, _subnodes, _supernode, and other properties which are accessed from multiple threads. diff --git a/AsyncDisplayKit/Private/ASStackPositionedLayout.h b/AsyncDisplayKit/Private/ASStackPositionedLayout.h index 211bda5b..2ff9e526 100644 --- a/AsyncDisplayKit/Private/ASStackPositionedLayout.h +++ b/AsyncDisplayKit/Private/ASStackPositionedLayout.h @@ -10,7 +10,6 @@ #import "ASLayout.h" #import "ASDimension.h" -#import "ASStackLayoutSpec.h" #import "ASStackUnpositionedLayout.h" /** Represents a set of laid out and positioned stack layout children. */ diff --git a/AsyncDisplayKit/Private/_ASHierarchyChangeSet.h b/AsyncDisplayKit/Private/_ASHierarchyChangeSet.h index b1f39cbf..a2547ff0 100644 --- a/AsyncDisplayKit/Private/_ASHierarchyChangeSet.h +++ b/AsyncDisplayKit/Private/_ASHierarchyChangeSet.h @@ -7,7 +7,9 @@ // #import -#import "ASDataController.h" +#import + +typedef NSUInteger ASDataControllerAnimationOptions; typedef NS_ENUM(NSInteger, _ASHierarchyChangeType) { _ASHierarchyChangeTypeReload, From 7b0c82b0acde57ec33cc1ecf9a0175f40c58f4e9 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Fri, 25 Dec 2015 19:34:45 -0800 Subject: [PATCH 59/60] Update to use iOS 9.2 simulator for testing, as Xcode 7.2 Travis apparently lacks 9.0. --- build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 935a0a9b..d2f19504 100755 --- a/build.sh +++ b/build.sh @@ -1,8 +1,8 @@ #!/bin/bash # **** Update me when new Xcode versions are released! **** -PLATFORM="platform=iOS Simulator,OS=9.0,name=iPhone 6" -SDK="iphonesimulator9.0" +PLATFORM="platform=iOS Simulator,OS=9.2,name=iPhone 6" +SDK="iphonesimulator9.2" # It is pitch black. From 7dff6ffa149153998c6deb255accbe1f00383645 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Fri, 25 Dec 2015 22:13:35 -0800 Subject: [PATCH 60/60] Re-enable program flow instrumentation for Coveralls. More null-specifiers. This does cause tests to crash at the end, which unfortunately seems like a known Xcode 7 bug. --- AsyncDisplayKit-Prefix.gcda | Bin 656 -> 0 bytes AsyncDisplayKit.xcodeproj/project.pbxproj | 16 +++++++------- AsyncDisplayKit/ASDisplayNode.h | 23 +++++++++----------- AsyncDisplayKit/ASEditableTextNode.h | 6 ++--- AsyncDisplayKit/Details/ASDataController.mm | 1 + 5 files changed, 22 insertions(+), 24 deletions(-) delete mode 100644 AsyncDisplayKit-Prefix.gcda diff --git a/AsyncDisplayKit-Prefix.gcda b/AsyncDisplayKit-Prefix.gcda deleted file mode 100644 index 83c74d3faa7677539da52471bcce34199dab999b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 656 zcmb`E%}T^D6on`Ltwix3T)EbbGo!;e;G#HP3`miQZWIYIy-tgv8IrWncknG-&s(_h z8Ql9E-n4<4ML`7v=iW3V-#v%&SWJ#Pr)RBtkxjpGZ5?&;5Kx-&sY#T*1!J$cfg>h) zsd5`+@h~-0{D@QxgGc|AU?*Fy_=64X%^VFP*Cs7MmeTZgo~F{mUIy}o<|r%7Q+JDb{T8;3aFr1 zn6YSLa?=lJoi?KEf=j6cw@Qy_mxWwUT0E2ztl;LYWB=M}e&@B#!rWKZ}{ uMt6Po7d}pk5J&d0tfG3e+3U`K@Xv(=uB!|#tebI&WexR7-oFlhnDGsPqqmj- diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 1cc2d937..3a920cc5 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -1934,7 +1934,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", @@ -1955,7 +1955,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; INFOPLIST_FILE = AsyncDisplayKitTestHost/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 7.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -2043,7 +2043,7 @@ APPLICATION_EXTENSION_API_ONLY = YES; DSTROOT = /tmp/AsyncDisplayKit.dst; GCC_INPUT_FILETYPE = automatic; - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "AsyncDisplayKit/AsyncDisplayKit-Prefix.pch"; GCC_TREAT_WARNINGS_AS_ERRORS = YES; @@ -2062,7 +2062,7 @@ APPLICATION_EXTENSION_API_ONLY = YES; DSTROOT = /tmp/AsyncDisplayKit.dst; GCC_INPUT_FILETYPE = automatic; - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "AsyncDisplayKit/AsyncDisplayKit-Prefix.pch"; GCC_TREAT_WARNINGS_AS_ERRORS = YES; @@ -2085,7 +2085,7 @@ "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)", ); - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "AsyncDisplayKit/AsyncDisplayKit-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -2113,7 +2113,7 @@ "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)", ); - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "AsyncDisplayKit/AsyncDisplayKit-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -2142,7 +2142,7 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -2175,7 +2175,7 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = "$(SRCROOT)/AsyncDisplayKit-iOS/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index cad8539a..84d29f0f 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -15,8 +15,6 @@ #import #import -NS_ASSUME_NONNULL_BEGIN - @class ASDisplayNode; /** @@ -37,7 +35,7 @@ typedef CALayer * _Nonnull(^ASDisplayNodeLayerBlock)(); /** * ASDisplayNode loaded callback block. This block is called BEFORE the -didLoad method and is always called on the main thread. */ -typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); +typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode * _Nonnull node); /** Interface state is available on ASDisplayNode and ASViewController, and @@ -86,6 +84,7 @@ typedef NS_OPTIONS(NSUInteger, ASInterfaceState) * */ +NS_ASSUME_NONNULL_BEGIN @interface ASDisplayNode : ASDealloc2MainObject @@ -195,7 +194,7 @@ typedef NS_OPTIONS(NSUInteger, ASInterfaceState) * @warning The first access to it must be on the main thread, and should only be used on the main thread thereafter as * well. */ -@property (nonatomic, readonly, retain) CALayer *layer; +@property (nonatomic, readonly, retain) CALayer * _Nonnull layer; /** * @abstract Returns the Interface State of the node. @@ -568,7 +567,7 @@ typedef NS_OPTIONS(NSUInteger, ASInterfaceState) @end - +NS_ASSUME_NONNULL_END /** * ## UIView bridge * @@ -599,7 +598,7 @@ typedef NS_OPTIONS(NSUInteger, ASInterfaceState) */ - (void)setNeedsLayout; -@property (atomic, retain) id contents; // default=nil +@property (atomic, retain, nullable) id contents; // default=nil @property (atomic, assign) BOOL clipsToBounds; // default==NO @property (atomic, getter=isOpaque) BOOL opaque; // default==YES @@ -644,12 +643,12 @@ typedef NS_OPTIONS(NSUInteger, ASInterfaceState) @property (atomic, assign, getter=isUserInteractionEnabled) BOOL userInteractionEnabled; // default=YES (NO for layer-backed nodes) @property (atomic, assign, getter=isExclusiveTouch) BOOL exclusiveTouch; // default=NO -@property (atomic, assign) CGColorRef shadowColor; // default=opaque rgb black +@property (atomic, assign, nullable) CGColorRef shadowColor; // default=opaque rgb black @property (atomic, assign) CGFloat shadowOpacity; // default=0.0 @property (atomic, assign) CGSize shadowOffset; // default=(0, -3) @property (atomic, assign) CGFloat shadowRadius; // default=3 @property (atomic, assign) CGFloat borderWidth; // default=0 -@property (atomic, assign) CGColorRef borderColor; // default=opaque rgb black +@property (atomic, assign, nullable) CGColorRef borderColor; // default=opaque rgb black // UIResponder methods // By default these fall through to the underlying view, but can be overridden. @@ -658,7 +657,7 @@ typedef NS_OPTIONS(NSUInteger, ASInterfaceState) - (BOOL)canResignFirstResponder; // default==YES - (BOOL)resignFirstResponder; // default==NO (no-op) - (BOOL)isFirstResponder; -- (BOOL)canPerformAction:(SEL)action withSender:(id)sender; +- (BOOL)canPerformAction:(nonnull SEL)action withSender:(nonnull id)sender; // Accessibility support @property (atomic, assign) BOOL isAccessibilityElement; @@ -691,7 +690,7 @@ typedef NS_OPTIONS(NSUInteger, ASInterfaceState) * * @param node The node to be added. */ -- (void)addSubnode:(ASDisplayNode *)node; +- (void)addSubnode:(nonnull ASDisplayNode *)node; @end /** CALayer(AsyncDisplayKit) defines convenience method for adding sub-ASDisplayNode to a CALayer. */ @@ -701,7 +700,7 @@ typedef NS_OPTIONS(NSUInteger, ASInterfaceState) * * @param node The node to be added. */ -- (void)addSubnode:(ASDisplayNode *)node; +- (void)addSubnode:(nonnull ASDisplayNode *)node; @end @@ -712,5 +711,3 @@ typedef NS_OPTIONS(NSUInteger, ASInterfaceState) @property (nonatomic, assign) BOOL placeholderFadesOut ASDISPLAYNODE_DEPRECATED; @end - -NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASEditableTextNode.h b/AsyncDisplayKit/ASEditableTextNode.h index fff4a6d8..983bfcd6 100644 --- a/AsyncDisplayKit/ASEditableTextNode.h +++ b/AsyncDisplayKit/ASEditableTextNode.h @@ -30,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly, strong) UITextView *textView; //! @abstract The attributes to apply to new text being entered by the user. -@property (nonatomic, readwrite, strong) NSDictionary *typingAttributes; +@property (nonatomic, readwrite, strong, nullable) NSDictionary *typingAttributes; //! @abstract The range of text currently selected. If length is zero, the range is the cursor location. @property (nonatomic, readwrite, assign) NSRange selectedRange; @@ -47,14 +47,14 @@ NS_ASSUME_NONNULL_BEGIN @abstract The styled placeholder text displayed by the text node while no text is entered @discussion The placeholder is displayed when the user has not entered any text and the keyboard is not visible. */ -@property (nonatomic, readwrite, strong) NSAttributedString *attributedPlaceholderText; +@property (nonatomic, readwrite, strong, nullable) NSAttributedString *attributedPlaceholderText; #pragma mark - Modifying User Text /** @abstract The styled text displayed by the receiver. @discussion When the placeholder is displayed (as indicated by -isDisplayingPlaceholder), this value is nil. Otherwise, this value is the attributed text the user has entered. This value can be modified regardless of whether the receiver is the first responder (and thus, editing) or not. Changing this value from nil to non-nil will result in the placeholder being hidden, and the new value being displayed. */ -@property (nonatomic, readwrite, copy) NSAttributedString *attributedText; +@property (nonatomic, readwrite, copy, nullable) NSAttributedString *attributedText; #pragma mark - Managing The Keyboard //! @abstract The text input mode used by the receiver's keyboard, if it is visible. This value is undefined if the receiver is not the first responder. diff --git a/AsyncDisplayKit/Details/ASDataController.mm b/AsyncDisplayKit/Details/ASDataController.mm index aa774b5b..bcc98f47 100644 --- a/AsyncDisplayKit/Details/ASDataController.mm +++ b/AsyncDisplayKit/Details/ASDataController.mm @@ -17,6 +17,7 @@ #import "ASMultidimensionalArrayUtils.h" #import "ASInternalHelpers.h" #import "ASLayout.h" +#import "ASFlowLayoutController.h" //#define LOG(...) NSLog(__VA_ARGS__) #define LOG(...)