28

I'm having a problem when using addSubview.

Example code:

ParentView *myParentView = [[ParentView alloc] initWithNibName:@"ParentView " bundle:nil];
ChildeView *myChildeView = [[ChildeView alloc] initWithNibName:@"ChildeView" bundle:nil];

//...  parent frame resized with setFrame lets say to x:0, y:0, W:320, H:411

[[myParentView view] addSubview: [myChildeView view]];

My child when added is bigger then the parent, and does not resize its frame to parent bounds. I can't use "clip subviews" on the parent, and "Autoresize Subviews" seems not to work if the parent frame is not resized again. Is there a property that makes a subview resize automatically to its parent's bounds without using setFrame on every child?

Shekhar Gupta
  • 6,206
  • 3
  • 30
  • 50
Luca
  • 383
  • 2
  • 5
  • 6

6 Answers6

39

If you aren’t using Auto Layout, have you tried setting the child view’s autoresize mask? Try this:

myChildeView.autoresizingMask = (UIViewAutoresizingFlexibleWidth |
                                 UIViewAutoresizingFlexibleHeight);

Also, you may need to call

myParentView.autoresizesSubviews = YES;

to get the parent view to resize its subviews automatically when its frame changes.

If you’re still seeing the child view drawing outside of the parent view’s frame, there’s a good chance that the parent view is not clipping its contents. To fix that, call

myParentView.clipsToBounds = YES;
Jeff Kelley
  • 19,021
  • 6
  • 70
  • 80
  • Thanks for the answer, although it doesn't work. But why isn't this the default UIView behavior. Am i produceing funny code? And why clip Subviews on the other hand works? – Luca Nov 17 '09 at 17:44
  • Are you changing the frame of the parent view before you add the child view? – Jeff Kelley Nov 17 '09 at 18:38
  • Yes, always getting the same problem. – Luca Nov 18 '09 at 12:12
  • 2
    I think you're just going to have to call setFrame when you add the child view. Sorry. – Jeff Kelley Nov 18 '09 at 16:01
  • This doesn't work. It's a bug in Apple's SDK, I have no idea what causes it, except it seems to be related to the childview being larger than the parent. It *seems* that Apple's got a typo in their source code somewhere, so that they're incorrectly ignoring the add. – Adam Aug 06 '10 at 12:43
  • For Swift: https://stackoverflow.com/questions/30867325/binary-operator-cannot-be-applied-to-two-uiviewautoresizing-operands – Yi Jiang Jan 25 '17 at 07:15
12

Just copy the parent view's frame to the child-view then add it. After that autoresizing will work. Actually you should only copy the size CGRectMake(0, 0, parentView.frame.size.width, parentView.frame.size.height)

childView.frame = CGRectMake(0, 0, parentView.frame.size.width, parentView.frame.size.height);
[parentView addSubview:childView];
cat
  • 2,871
  • 1
  • 23
  • 28
  • But this is not an autoresize, it's just a clone mesures from the parentView – lojals Feb 12 '16 at 17:10
  • That's why I added "After that autoresizing will work." You can set it in XCode's Interface Builder, or as stated in other answers here. If the subview has a strange geometry within its parent, autoresizing will produce strange results. – cat Jul 31 '16 at 09:52
  • Can confirm, this is awesome. I had an embedded NSSplitView with issues, and this tuned it right up. swift looks like: childView.frame =NSRect(x:0, y:0, width:parentView.frame.size.width, height:parentView.frame.size.height); parentView.addSubview(childView); – Stickley Aug 10 '18 at 02:01
8

that's all you need

childView.frame = parentView.bounds
Carmen
  • 6,177
  • 1
  • 35
  • 40
5

Tested in Xcode 9.4, Swift 4 Another way to solve this issue is , You can add

override func layoutSubviews() {
        self.frame = (self.superview?.bounds)!
    }

in subview class.

Sangram Shivankar
  • 3,535
  • 3
  • 26
  • 38
Zeesha
  • 991
  • 9
  • 14
2

Swift 4 extension using explicit constraints:

import UIKit.UIView

extension UIView {
    public func addSubview(_ subview: UIView, stretchToFit: Bool = false) {
        addSubview(subview)
        if stretchToFit {
            subview.translatesAutoresizingMaskIntoConstraints = false
            leftAnchor.constraint(equalTo: subview.leftAnchor).isActive = true
            rightAnchor.constraint(equalTo: subview.rightAnchor).isActive = true
            topAnchor.constraint(equalTo: subview.topAnchor).isActive = true
            bottomAnchor.constraint(equalTo: subview.bottomAnchor).isActive = true
        }
    }
}

Usage:

parentView.addSubview(childView) // won't resize (default behavior unchanged)
parentView.addSubview(childView, stretchToFit: false) // won't resize
parentView.addSubview(childView, stretchToFit: true) // will resize
agirault
  • 2,509
  • 20
  • 24
1

You can always do it in your UIViews - (void)didMoveToSuperview method. It will get called when added or removed from your parent (nil when removed). At that point in time just set your size to that of your parent. From that point on the autoresize mask should work properly.

Sean
  • 41
  • 2
  • 3
  • Informs the receiver that its superview has changed (possibly to nil). It seems that it doesn't fire at addSubview. – Luca Nov 18 '09 at 12:06