diff --git a/AsyncDisplayKit/ASViewController.mm b/AsyncDisplayKit/ASViewController.mm index 7cb031a11a..710016ccef 100644 --- a/AsyncDisplayKit/ASViewController.mm +++ b/AsyncDisplayKit/ASViewController.mm @@ -9,8 +9,11 @@ #import "ASViewController.h" #import "ASAssert.h" #import "ASDimension.h" +#import "ASDisplayNodeInternal.h" #import "ASDisplayNode+FrameworkPrivate.h" #import "ASDisplayNode+Beta.h" +#import "ASTraitCollection.h" +#import "ASEnvironmentInternal.h" #import "ASRangeControllerUpdateRangeProtocol+Beta.h" #define AS_LOG_VISIBILITY_CHANGES 0 @@ -46,10 +49,21 @@ _node = node; _automaticallyAdjustRangeModeBasedOnViewEvents = NO; - + return self; } +- (void)dealloc +{ + if (_traitColectionContext != nil) { + // The setter will iterate through the VC's subnodes and replace the traitCollectionContext in their ASEnvironmentTraitCollection with nil. + // Since the VC holds the only strong reference to this context and we are in the process of destroying + // the VC, all the references in the subnodes will be unsafe unless we nil them out. More than likely all the subnodes will be dealloc'ed + // as part of the VC being dealloc'ed, but this is just to make extra sure. + self.traitColectionContext = nil; + } +} + - (void)loadView { ASDisplayNodeAssertTrue(!_node.layerBacked); @@ -171,4 +185,80 @@ ASVisibilityDepthImplementation; return _node.interfaceState; } +#pragma mark - ASEnvironmentTraitCollection + +- (void)setTraitColectionContext:(id)traitColectionContext +{ + if (_traitColectionContext != traitColectionContext) { + // propagate first so that nodes aren't hanging around with a dealloc'ed pointer + ASEnvironmentTraitCollectionUpdateDisplayContext(self.node, traitColectionContext); + + _traitColectionContext = traitColectionContext; + } +} + +- (ASEnvironmentTraitCollection)displayTraitsForTraitCollection:(UITraitCollection *)traitCollection +{ + if (self.overrideDisplayTraitsWithTraitCollection) { + ASTraitCollection *asyncTraitCollection = self.overrideDisplayTraitsWithTraitCollection(traitCollection); + self.traitColectionContext = asyncTraitCollection.traitCollectionContext; + return [asyncTraitCollection environmentTraitCollection]; + } + + ASEnvironmentTraitCollection asyncTraitCollection = ASEnvironmentTraitCollectionFromUITraitCollection(traitCollection); + asyncTraitCollection.displayContext = self.traitColectionContext; + return asyncTraitCollection; +} + +- (ASEnvironmentTraitCollection)displayTraitsForWindowSize:(CGSize)windowSize +{ + if (self.overrideDisplayTraitsWithWindowSize) { + ASTraitCollection *traitCollection = self.overrideDisplayTraitsWithWindowSize(windowSize); + self.traitColectionContext = traitCollection.traitCollectionContext; + return [traitCollection environmentTraitCollection]; + } + return self.node.environmentTraitCollection; +} + +- (void)progagateNewDisplayTraits:(ASEnvironmentTraitCollection)traitCollection +{ + ASEnvironmentState environmentState = self.node.environmentState; + ASEnvironmentTraitCollection oldTraitCollection = environmentState.traitCollection; + + if (ASEnvironmentTraitCollectionIsEqualToASEnvironmentTraitCollection(traitCollection, oldTraitCollection) == NO) { + environmentState.traitCollection = traitCollection; + self.node.environmentState = environmentState; + [self.node setNeedsLayout]; + + NSArray> *children = [self.node children]; + for (id child in children) { + ASEnvironmentStatePropagateDown(child, environmentState.traitCollection); + } + } +} + +- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection +{ + [super traitCollectionDidChange:previousTraitCollection]; + + ASEnvironmentTraitCollection traitCollection = [self displayTraitsForTraitCollection:self.traitCollection]; + [self progagateNewDisplayTraits:traitCollection]; +} + +- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id)coordinator +{ + [super willTransitionToTraitCollection:newCollection withTransitionCoordinator:coordinator]; + + ASEnvironmentTraitCollection traitCollection = [self displayTraitsForTraitCollection:newCollection]; + [self progagateNewDisplayTraits:traitCollection]; +} + +- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator +{ + [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; + + ASEnvironmentTraitCollection traitCollection = [self displayTraitsForWindowSize:size]; + [self progagateNewDisplayTraits:traitCollection]; +} + @end