Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can a UIView get a callback when it is added to its superview?

Problem

I have subclassed a UIView. After an object of this subclass is added to its superview, it needs to autonomously run some code. How can I hook on to this event to run my code?

Why I Need It

The background of the selected segmented of a UISegmentedControl has been notoriously hard to style. The best solution I could find is doing this hack:

#import "SegmentedControlStyled.h"

@implementation SegmentedControlStyled

- (void) updateStyle
{
    for (NSUInteger i = 0; i < [self.subviews count]; i++) {
        if ([[self.subviews objectAtIndex:i] respondsToSelector:@selector(isSelected)] && [[self.subviews objectAtIndex:i] isSelected]) {
            [[self.subviews objectAtIndex:i] setTintColor:[UIColor colorWithWhite:0.7 alpha:1.0]];
        }
        if ([[self.subviews objectAtIndex:i] respondsToSelector:@selector(isSelected)] && ![[self.subviews objectAtIndex:i] isSelected]) {
            [[self.subviews objectAtIndex:i] setTintColor:[UIColor colorWithWhite:0.9 alpha:1.0]];
        }
    }
}

@end

This updateStyle function needs to be called in two places. Obviously, the first is whenever the a user taps a different segment. I can do this autonomously by overriding my SegmentedControlStyled's addTarget function and hooking on to the UIControlEventValueChanged event. The second place updateStyle needs to be called is after a SegmentedControlStyled is added to its superview. You may ask, "why do you call it after and not somewhere like init?". Well, from my observations, calling it before it is attached to the view hiearchy has no effect. Therefore, one needs to write their code like this:

SegmentedControlStyled* seg = [[SegmentedControlStyled alloc] initWithItems:[NSArray arrayWithObjects:@"One", @"Two", nil]];
[self.view addSubview:seg];
[seg updateStyle];

The last line is ugly, because the co-worker who uses my subclass has to understand why the view is broken and has to know when to call updateStyle. To uphold the Object Oriented principle of encapsulation, this detail should be moved into the class itself. If I had the ability to detect when a view has been added to its superview, I would be able to encapsulate the style hack within my subclass.

like image 818
Pwner Avatar asked Jul 22 '13 19:07

Pwner


People also ask

Does removing from superview remove constraints?

Calling this method removes any constraints that refer to the view you are removing, or that refer to any view in the subtree of the view you are removing. Never call this method from inside your view's draw(_:) method.

How do I present UIView in Swift?

present the gray UIView like you would usually present a ViewController (appearing bottom up and user can slide down to dismiss). The bottomBar is a ContainerView and should not change by switching between the VC's, only the gray UIView which you can see in the 2nd picture.


1 Answers

override either of

- (void)didAddSubview:(UIView *)subview
- (void)willMoveToSuperview:(UIView *)newSuperview
- (void)willMoveToWindow:(UIWindow *)newWindow

as appropriate?

like image 163
verec Avatar answered Sep 18 '22 11:09

verec