diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index 5313719336..006f8776b0 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -55,6 +55,12 @@ typedef void (^ASDisplayNodeContextModifier)(CGContextRef context); */ typedef ASLayoutSpec * _Nonnull(^ASLayoutSpecBlock)(__kindof ASDisplayNode * _Nonnull node, ASSizeRange constrainedSize); +/** + * AsyncDisplayKit non-faltal 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 @@ -252,6 +258,15 @@ 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 anormal behavior, but + * still gives the opportunity to use a reporting mechanism to catch occurrences in production. + * + * @warning This method is not thread-safe. + */ +@property (nonatomic, class, copy) ASDisplayNodeNonFatalErrorBlock nonFatalErrorBlock; + /** @name Managing dimensions */ diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index b9b9d9ca20..81e78e059f 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -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; @@ -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