Skip to content
This repository has been archived by the owner on Feb 2, 2023. It is now read-only.

[ASDisplayNode] Add support for setting non-fatal error block #2993

Merged
merged 6 commits into from
Feb 8, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions AsyncDisplayKit/ASDisplayNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ typedef void (^ASDisplayNodeContextModifier)(CGContextRef context);
*/
typedef ASLayoutSpec * _Nonnull(^ASLayoutSpecBlock)(__kindof ASDisplayNode * _Nonnull node, ASSizeRange constrainedSize);

/**
* AsyncDisplayKit non-fatal error block. This block can be used for handling non-fatal errors. Useful for reporting
* errors that happens in production.
*/
typedef void (^ASDisplayNodeNonFatalErrorBlock)(__kindof NSError * _Nonnull error);

/**
* Interface state is available on ASDisplayNode and ASViewController, and
* allows checking whether a node is in an interface situation where it is prudent to trigger certain
Expand Down Expand Up @@ -252,6 +258,16 @@ extern NSInteger const ASDefaultDrawingPriority;
*/
@property (readonly) ASInterfaceState interfaceState;

/**
* @abstract Class property that allows to set a block that can be called on non-fatal errors. This
* property can be useful for cases when Async Display Kit can recover from an abnormal behavior, but
* still gives the opportunity to use a reporting mechanism to catch occurrences in production. In
* development, Async Display Kit will assert instead of calling this block.
*
* @warning This method is not thread-safe.
*/
@property (nonatomic, class, copy) ASDisplayNodeNonFatalErrorBlock nonFatalErrorBlock;


/** @name Managing dimensions */

Expand Down
16 changes: 16 additions & 0 deletions AsyncDisplayKit/ASDisplayNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
#define TIME_SCOPED(outVar)
#endif

static ASDisplayNodeNonFatalErrorBlock _nonFatalErrorBlock = nil;

// Forward declare CALayerDelegate protocol as the iOS 10 SDK moves CALayerDelegate from a formal delegate to a protocol.
// We have to forward declare the protocol as this place otherwise it will not compile compiling with an Base SDK < iOS 10
@protocol CALayerDelegate;
Expand Down Expand Up @@ -2259,6 +2261,20 @@ - (void)subnodeDisplayDidFinish:(ASDisplayNode *)subnode
return (id)kCFNull;
}

#pragma mark - Error Handling

+ (void)setNonFatalErrorBlock:(ASDisplayNodeNonFatalErrorBlock)nonFatalErrorBlock
{
if (_nonFatalErrorBlock != nonFatalErrorBlock) {
_nonFatalErrorBlock = [nonFatalErrorBlock copy];
}
}

+ (ASDisplayNodeNonFatalErrorBlock)nonFatalErrorBlock
{
return _nonFatalErrorBlock;
}

#pragma mark - Converting to and from the Node's Coordinate System

- (CATransform3D)_transformToAncestor:(ASDisplayNode *)ancestor
Expand Down
16 changes: 16 additions & 0 deletions Base/ASAssert.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,19 @@
#define ASDisplayNodeCAssertPositiveReal(description, num) ASDisplayNodeCAssert(num >= 0 && num <= CGFLOAT_MAX, @"%@ must be a real positive integer.", description)
#define ASDisplayNodeCAssertInfOrPositiveReal(description, num) ASDisplayNodeCAssert(isinf(num) || (num >= 0 && num <= CGFLOAT_MAX), @"%@ must be infinite or a real positive integer.", description)

#define ASDisplayNodeErrorDomain @"ASDisplayNodeErrorDomain"
#define ASDisplayNodeNonFatalErrorCode 1

#define ASDisplayNodeAssertNonFatal(condition, desc, ...) \
ASDisplayNodeAssert(condition, desc, ##__VA_ARGS__); \
if (condition == NO) { \
ASDisplayNodeNonFatalErrorBlock block = [ASDisplayNode nonFatalErrorBlock]; \
if (block != nil) { \
NSDictionary *userInfo = nil; \
if (desc.length > 0) { \
userInfo = @{ NSLocalizedDescriptionKey : desc }; \
} \
NSError *error = [NSError errorWithDomain:ASDisplayNodeErrorDomain code:ASDisplayNodeNonFatalErrorCode userInfo:userInfo]; \
block(error); \
} \
}