Scott Goodson 21bebb9d29 [ASRangeController] Improvements to application state change and memory warning handling.
Introduces ASLayoutRangeModeVisibleOnly, allowing the preservation of decoded backing stores without any extra padding to
strictly minimize memory usage while supporting immediate re-display of content.  Set visible range controllers to this mode
upon app suspend / memory warning, while more aggressively clearing others to the ASLayoutRangeModeLowMemory mode.

By default, when the app is running and recieves a memory warning, we set the range mode for non-visible controllers to
ASLayoutRangeModeVisibleOnly.  This is because, unlike in the app suspend case where on app resume we can restore controllers
from LowMemory to VisibleOnly, the memory warning doesn't provide a good opportunity to do this.

A new +Beta API to control this behavior is called +setRangeModeForMemoryWarnings:, as some apps may prefer to use LowMemory
in the memory warning scenario.  For these apps, optimal user experience will require manually setting the range mode back
to some larger value as the user navigates the app, or they will encounter controllers that are temporarily blank and need
a moment to re-display their contents as they start to become visible.
2016-03-09 21:22:45 -08:00

82 lines
1.6 KiB
Objective-C

//
// ASWeakSet.m
// AsyncDisplayKit
//
// Created by Adlai Holler on 1/7/16.
// Copyright © 2016 Facebook. All rights reserved.
//
#import "ASWeakSet.h"
@interface ASWeakSet<__covariant ObjectType> ()
@property (nonatomic, strong, readonly) NSMapTable<ObjectType, NSNull *> *mapTable;
@end
@implementation ASWeakSet
- (instancetype)init
{
self = [super init];
if (self) {
_mapTable = [NSMapTable weakToStrongObjectsMapTable];
}
return self;
}
- (void)addObject:(id)object
{
[_mapTable setObject:[NSNull null] forKey:object];
}
- (void)removeObject:(id)object
{
[_mapTable removeObjectForKey:object];
}
- (void)removeAllObjects
{
[_mapTable removeAllObjects];
}
- (BOOL)containsObject:(id)object
{
return [_mapTable objectForKey:object] != nil;
}
- (BOOL)isEmpty
{
for (__unused id object in _mapTable) {
return NO;
}
return YES;
}
/**
Note: The `count` property of NSMapTable is unreliable
in the case of weak-to-strong map tables because entries
whose keys have been deallocated are not removed immediately.
In order to get the true count we have to fall back to using
fast enumeration.
*/
- (NSUInteger)count
{
NSUInteger count = 0;
for (__unused id object in _mapTable) {
count += 1;
}
return count;
}
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unsafe_unretained id _Nonnull *)buffer count:(NSUInteger)len
{
return [_mapTable countByEnumeratingWithState:state objects:buffer count:len];
}
- (NSString *)description
{
return [[super description] stringByAppendingFormat:@" count: %lu, contents: %@", self.count, _mapTable];
}
@end