简体   繁体   中英

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.

override either of

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

as appropriate?

UISegmentedControl's selected state isn't hard to style.

You use the method setBackgroundImage:forState:barMetrics: and use UIControlStateSelected as the argument for named parameter forState: .

Anything where you are accessing subviews of UIKit controls is a bad thing™. You shouldn't rely on internal implementation details.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM