Skip to content

Commit b33cced

Browse files
rmlsgarrettmoon
authored andcommitted
[ASDisplayNode] Add support for setting non-fatal error block (facebookarchive#2993)
* Add support for setting non-fatal error block * Better documentation and fix typos * Added ASDisplayNodeAssertNonFatal macro that asserts in dev and call block in prod * Make non fatal error code equals to 1 * Add support for condition in ASDisplayNodeAssertNonFatal * Only call non fatal block if condition isn’t satisfied
1 parent f212545 commit b33cced

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

AsyncDisplayKit/ASDisplayNode.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ typedef void (^ASDisplayNodeContextModifier)(CGContextRef context);
5656
*/
5757
typedef ASLayoutSpec * _Nonnull(^ASLayoutSpecBlock)(__kindof ASDisplayNode * _Nonnull node, ASSizeRange constrainedSize);
5858

59+
/**
60+
* AsyncDisplayKit non-fatal error block. This block can be used for handling non-fatal errors. Useful for reporting
61+
* errors that happens in production.
62+
*/
63+
typedef void (^ASDisplayNodeNonFatalErrorBlock)(__kindof NSError * _Nonnull error);
64+
5965
/**
6066
* Interface state is available on ASDisplayNode and ASViewController, and
6167
* allows checking whether a node is in an interface situation where it is prudent to trigger certain
@@ -253,6 +259,16 @@ extern NSInteger const ASDefaultDrawingPriority;
253259
*/
254260
@property (readonly) ASInterfaceState interfaceState;
255261

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

257273
/** @name Managing dimensions */
258274

AsyncDisplayKit/ASDisplayNode.mm

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@
6363
#define TIME_SCOPED(outVar)
6464
#endif
6565

66+
static ASDisplayNodeNonFatalErrorBlock _nonFatalErrorBlock = nil;
67+
6668
// Forward declare CALayerDelegate protocol as the iOS 10 SDK moves CALayerDelegate from a formal delegate to a protocol.
6769
// We have to forward declare the protocol as this place otherwise it will not compile compiling with an Base SDK < iOS 10
6870
@protocol CALayerDelegate;
@@ -2250,6 +2252,20 @@ - (void)subnodeDisplayDidFinish:(ASDisplayNode *)subnode
22502252
return (id)kCFNull;
22512253
}
22522254

2255+
#pragma mark - Error Handling
2256+
2257+
+ (void)setNonFatalErrorBlock:(ASDisplayNodeNonFatalErrorBlock)nonFatalErrorBlock
2258+
{
2259+
if (_nonFatalErrorBlock != nonFatalErrorBlock) {
2260+
_nonFatalErrorBlock = [nonFatalErrorBlock copy];
2261+
}
2262+
}
2263+
2264+
+ (ASDisplayNodeNonFatalErrorBlock)nonFatalErrorBlock
2265+
{
2266+
return _nonFatalErrorBlock;
2267+
}
2268+
22532269
#pragma mark - Converting to and from the Node's Coordinate System
22542270

22552271
- (CATransform3D)_transformToAncestor:(ASDisplayNode *)ancestor

Base/ASAssert.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,19 @@
5959
#define ASDisplayNodeCAssertPositiveReal(description, num) ASDisplayNodeCAssert(num >= 0 && num <= CGFLOAT_MAX, @"%@ must be a real positive integer.", description)
6060
#define ASDisplayNodeCAssertInfOrPositiveReal(description, num) ASDisplayNodeCAssert(isinf(num) || (num >= 0 && num <= CGFLOAT_MAX), @"%@ must be infinite or a real positive integer.", description)
6161

62+
#define ASDisplayNodeErrorDomain @"ASDisplayNodeErrorDomain"
63+
#define ASDisplayNodeNonFatalErrorCode 1
64+
65+
#define ASDisplayNodeAssertNonFatal(condition, desc, ...) \
66+
ASDisplayNodeAssert(condition, desc, ##__VA_ARGS__); \
67+
if (condition == NO) { \
68+
ASDisplayNodeNonFatalErrorBlock block = [ASDisplayNode nonFatalErrorBlock]; \
69+
if (block != nil) { \
70+
NSDictionary *userInfo = nil; \
71+
if (desc.length > 0) { \
72+
userInfo = @{ NSLocalizedDescriptionKey : desc }; \
73+
} \
74+
NSError *error = [NSError errorWithDomain:ASDisplayNodeErrorDomain code:ASDisplayNodeNonFatalErrorCode userInfo:userInfo]; \
75+
block(error); \
76+
} \
77+
}

0 commit comments

Comments
 (0)