Question

To allow for flexible layouts, I wanted to create a subclass UIView that overrides layoutSubviews: to layout all of its subviews under each other automagically and would continue to do this every time one of its subviews got resized.

However, the only way that I can think of to let the superview know that it should call layoutSubviews: is by overriding that method in each of its subviews, something that I would like to try and avoid (I want people to be able to add arbitrary UIViews to the superview and have this taken care of).

Is there a way for the superview to call layoutSubviews: whenever a subview changes its size, without adding any code to the subview in question?

Was it helpful?

Solution

You could use KVO to observe the frame property of each of your subviews. You would need to add yourself as an observer each time a subview is added and remove the observation when a subview is removed – you can override didAddSubview: and willRemoveSubview: in your superview to do that.

- (void)didAddSubview:(UIView *)subview {
    [subview addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];
}

- (void)willRemoveSubview:(UIView *)subview {
    [subview removeObserver:self forKeyPath:@"frame"];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:@"frame"]) {
         // Do your layout here...
    }
}

- (void)dealloc {
    // You might need to remove yourself as an observer here, in case
    // your subviews are still used by others
}

OTHER TIPS

You can add a category to the class and try overriding layoutSubviews: from within the category. (This technique has been suggested for customizing navigation bars, and it may well work here too.)

Here's how you'd make a category, taken from my answer here. In your case, remember to substitute UIView for UINavigationController.

Hit Command+N or open the "New File" dialog. Next, choose "Objective-C category" from the Cocoa Touch menu:

Creating a category

Click Next and you will be prompted to enter the name of the class that you would like to add methods to as a category. It should look something like this:

Making a Category on the NavBar

Then, you should end up with a save file dialog. A quick note about convention here. Convention is to name a category after the original class, the plus sign, and then a description of what you're adding. Here's what yours might look like:

Category Naming Convention

Once you save your file, you will need get something like this:

Empty Category

Edit:

If you want to go ahead and do this without a category, then your best bet is to make a subclass of UIView and then subclass that class wherever you want your custom behavior. Another advantage over a category is that your method will only work where you explicitly use the custom class. In categories, the method gets added everywhere.

Good luck!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top