diff --git a/CTAppearance/CTAppearance+UIKit.m b/CTAppearance/CTAppearance+UIKit.m index e2bf67f..f62dfc2 100644 --- a/CTAppearance/CTAppearance+UIKit.m +++ b/CTAppearance/CTAppearance+UIKit.m @@ -19,7 +19,7 @@ static void _CTAppearanceReplaceClassSelector(Class klass, SEL srcSelector, SEL method_exchangeImplementations(dstMethod, srcMethod); } -static void _CTAppearanceReplaceInstanceSelector(Class klass, SEL srcSelector, SEL dstSelector) { +__unused static void _CTAppearanceReplaceInstanceSelector(Class klass, SEL srcSelector, SEL dstSelector) { Method srcMethod = class_getInstanceMethod(klass, srcSelector); Method dstMethod = class_getInstanceMethod(klass, dstSelector); method_exchangeImplementations(dstMethod, srcMethod); @@ -65,6 +65,7 @@ - (void)applyAppearanceForSuperview:(UIView*)superview { // Always apply the hierarchy appearances when moving superviews [CTAppearance applyContainedInTo: self forSuperview: superview]; + [self setAppliedAppearanceWindow:superview.window]; } - (void)willMoveToSuperview:(UIView *)newSuperview { @@ -82,8 +83,19 @@ - (void)didMoveToSuperview { } } +- (void)didMoveToWindow { + if (![CTAppearance isEnabled]) { return; } + + // If we moved to a new window, we need to re-check the hierarchy. Common need for UITableView subviews. + UIWindow *window = self.window; + if (window && window != [self appliedAppearanceWindow]) { + [CTAppearance applyContainedInTo: self forSuperview: self.superview]; + } + [self setAppliedAppearanceWindow:window]; +} + #pragma mark - -#pragma mark Associatd Objects +#pragma mark Associated Objects #pragma mark - - (void)setHasAppliedAppearance:(BOOL)hasApplied { objc_setAssociatedObject(self, &_property_hasAppliedKey, [NSNumber numberWithBool:hasApplied], OBJC_ASSOCIATION_RETAIN_NONATOMIC); @@ -92,4 +104,16 @@ - (void)setHasAppliedAppearance:(BOOL)hasApplied { - (BOOL)hasAppliedAppearance { return [objc_getAssociatedObject(self, &_property_hasAppliedKey) boolValue]; } -@end \ No newline at end of file + +static char * APPLIED_WINDOW = "_property_appliedAppearWindow"; + +- (void)setAppliedAppearanceWindow:(UIWindow *)window { + objc_setAssociatedObject(self, APPLIED_WINDOW, window, OBJC_ASSOCIATION_ASSIGN); +} + +- (id)appliedAppearanceWindow { + return objc_getAssociatedObject(self, APPLIED_WINDOW); +} + +@end + diff --git a/CTAppearance/CTAppearance.m b/CTAppearance/CTAppearance.m index 5a2de86..f925545 100644 --- a/CTAppearance/CTAppearance.m +++ b/CTAppearance/CTAppearance.m @@ -110,7 +110,16 @@ + (void)applyContainedInTo:(id)arg1 forSuperview:(id)superview { if (superviews == nil) { superviews = [NSMutableArray array]; + + [self collateViewControllersOfView:arg1 intoArray:superviews]; [self collateSuperviews: superview intoArray:superviews]; + + // NOTE: If the view is inside of a UIPopoverController, that should be added here at the + // end of the array, as it is also a UIAppearanceContainer. There does not seem to be any + // public API to determine that. If you are in a position to use private API, you could + // iterate through the superviews array here, and if any UIViewController instance has a + // popover set in its _popoverController instance variable, add it. If there is a local + // way to determine a current popover, use that. } for (CTAppearance *a in parents) { @@ -121,6 +130,7 @@ + (void)applyContainedInTo:(id)arg1 forSuperview:(id)superview { for (UIView *sv in superviews) { if ([sv isKindOfClass: c] || [sv isMemberOfClass:c]) { found = YES; + break; } } @@ -137,9 +147,23 @@ + (void)applyContainedInTo:(id)arg1 forSuperview:(id)superview { } } ++ (void)collateViewControllersOfView:(UIView*)view intoArray:(NSMutableArray *)svs +{ + id responder = [view nextResponder]; + if ([responder isKindOfClass:[UIViewController class]]) { + UIViewController *controller = responder; + while (controller) { + [svs addObject:controller]; + controller = controller.parentViewController; + } + + } +} + + (void)collateSuperviews:(UIView*)superview intoArray:(NSMutableArray*)svs { if (superview) { [svs addObject: superview]; + [self collateViewControllersOfView:superview intoArray:svs]; [self collateSuperviews:superview.superview intoArray:svs]; } }