Swiftgram/AsyncDisplayKit/Private/ASDisplayNodeInternal.h
Scott Goodson f7d91bb877 Implement -reclaimMemory API and switch to manually controlled content clearing.
ASDisplayNode and several subclasses had previously cleared memory-heavy
objects like the backing store and text layout manager when the node's
view
or layer is removed from a visible heirarchy.  This works great in any
system
that uses a "working range", where exiting the range removes the node
from
the hierarchy and reclaiming memory at that time is important.
However, for
standard UIViewController patterns (unused in Paper), this behavior
causes
highly undesirable thrashing (leading to visible flashes & wasteful
re-rendering of content).

After this change, node subclasses should implement -reclaimMemory if
they
need to perform any other cleanup besides backing store destruction
when they
leave a working range or other scenario where memory reduction is
valuable.

To trigger this behavior, calling code should use
-recursivelyReclaimMemory.

r=nadi
2014-10-14 18:45:56 -07:00

124 lines
4.1 KiB
Objective-C

/* Copyright (c) 2014-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.
*/
//
// The following methods are ONLY for use by _ASDisplayLayer, _ASDisplayView, and ASDisplayNode.
// 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"
#import "ASSentinel.h"
#import "ASThread.h"
BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector);
@class _ASPendingState;
// Allow 2^n increments of begin disabling hierarchy notifications
#define visibilityNotificationsDisabledBits 4
#define TIME_DISPLAYNODE_OPS (DEBUG || PROFILE)
@interface ASDisplayNode () <_ASDisplayLayerDelegate>
{
@protected
ASDN::RecursiveMutex _propertyLock; // Protects access to the _view, _pendingViewState, _subnodes, _supernode, _renderingSubnodes, and other properties which are accessed from multiple threads.
ASDisplayNode * __weak _supernode;
ASSentinel *_displaySentinel;
ASSentinel *_replaceAsyncSentinel;
// This is the desired contentsScale, not the scale at which the layer's contents should be displayed
CGFloat _contentsScaleForDisplay;
CGSize _size;
CGSize _constrainedSize;
UIEdgeInsets _hitTestSlop;
NSMutableArray *_subnodes;
Class _viewClass;
Class _layerClass;
UIView *_view;
CALayer *_layer;
_ASPendingState *_pendingViewState;
struct {
unsigned implementsDisplay:1;
unsigned isSynchronous:1;
unsigned isLayerBacked:1;
unsigned sizeCalculated:1;
unsigned preventOrCancelDisplay:1;
unsigned displaysAsynchronously:1;
unsigned shouldRasterizeDescendants:1;
unsigned visibilityNotificationsDisabled:visibilityNotificationsDisabledBits;
unsigned isInEnterHierarchy:1;
unsigned isInExitHierarchy:1;
unsigned inWindow:1;
unsigned hasWillDisplayAsyncLayer:1;
unsigned hasDrawParametersForAsyncLayer:1;
unsigned hasClassDisplay:1;
} _flags;
ASDisplayNodeExtraIvars _extra;
#if TIME_DISPLAYNODE_OPS
@public
NSTimeInterval _debugTimeToCreateView;
NSTimeInterval _debugTimeToApplyPendingState;
NSTimeInterval _debugTimeToAddSubnodeViews;
NSTimeInterval _debugTimeForDidLoad;
#endif
}
// The _ASDisplayLayer backing the node, if any.
@property (nonatomic, readonly, retain) _ASDisplayLayer *asyncLayer;
// Creates a pendingViewState if one doesn't exist. Allows setting view properties on a bg thread before there is a view.
@property (atomic, retain, readonly) _ASPendingState *pendingViewState;
// Swizzle to extend the builtin functionality with custom logic
- (BOOL)__shouldLoadViewOrLayer;
- (BOOL)__shouldSize;
- (void)__layout;
- (void)__setSupernode:(ASDisplayNode *)supernode;
// The visibility state of the node. Changed before calling willAppear, willDisappear, and didDisappear.
@property (nonatomic, readwrite, assign, getter = isInWindow) BOOL inWindow;
// Private API for helper funcitons / unit tests. Use ASDisplayNodeDisableHierarchyNotifications() to control this.
- (BOOL)__visibilityNotificationsDisabled;
- (void)__incrementVisibilityNotificationsDisabled;
- (void)__decrementVisibilityNotificationsDisabled;
// Call willEnterHierarchy if necessary and set inWindow = YES if visibility notifications are enabled on all of its parents
- (void)__enterHierarchy;
// Call didExitHierarchy if necessary and set inWindow = NO if visibility notifications are enabled on all of its parents
- (void)__exitHierarchy;
// Returns the ancestor node that rasterizes descendants, or nil if none.
- (ASDisplayNode *)__rasterizedContainerNode;
@property (nonatomic, assign) CGFloat contentsScaleForDisplay;
@end
@interface UIView (ASDisplayNodeInternal)
@property (nonatomic, assign, readwrite) ASDisplayNode *asyncdisplaykit_node;
@end
@interface CALayer (ASDisplayNodeInternal)
@property (nonatomic, assign, readwrite) ASDisplayNode *asyncdisplaykit_node;
@end