Reputation: 12141
I'm trying to add subview programmatically so people can horizontally scroll to another section. But it looks like the subview doesn't fit to SuperView and the content not showing
Here's my code from ViewController.m
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
for (int i = 0; i < 2; i++)
{
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.size = self.scrollView.frame.size;
self.scrollView.pagingEnabled = YES;
NewsSection *sectionView = [[NewsSection alloc] initWithFrame:frame];
[self.scrollView addSubview:sectionView];
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * 2, self.scrollView.frame.size.height);
}
This is my StoryBoard and constraints.
And this is my NewsSection.xib
This is my code of NewsSection.m
-(id) initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if(self) {
[[NSBundle mainBundle] loadNibNamed:@"NewsSection" owner:self options:nil];
[self addSubview:self.view];
}
return self;
}
And this is the result I'm seeing
UPDATE: Product code is here https://github.com/noppanit/UIScrollViewAutoLayout
Upvotes: 0
Views: 1174
Reputation: 2337
I'll start off with a good read regarding UIScrollView and Autolayout: https://developer.apple.com/library/ios/technotes/tn2154/_index.html
Now, here's some sample code that should keep you get going. You just need to make your NewsView
be managed by a ViewController, e.g. NewsViewController
, and initialize NewsViewController
before using it in setupNewsView
:
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupNewsView];
}
- (void) setupNewsView
{
UIView *newsView = [[NewsSection alloc] initWithFrame:CGRectZero];
self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;
newsView.translatesAutoresizingMaskIntoConstraints = NO;
[self.scrollView addSubview:newsView];
NSDictionary *viewsDict = @{ @"newsView": newsView };
[self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[newsView]|"
options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom
metrics:nil
views:viewsDict]];
[self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[newsView]|"
options:0
metrics:nil
views:viewsDict]];
[self.scrollView addConstraint:[NSLayoutConstraint constraintWithItem:newsView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.scrollView
attribute:NSLayoutAttributeWidth
multiplier:1.0f
constant:0.0f]];
[self.scrollView addConstraint:[NSLayoutConstraint constraintWithItem:newsView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self.scrollView
attribute:NSLayoutAttributeHeight
multiplier:1.0f
constant:0.0f]];
}
I'm sorry. I missed to add this line in my solution before:
[self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[newsView]|"
options:0
metrics:nil
views:viewsDict]];
Regarding your code sample: First, fill your ViewController
exactly as my code sample depicts. I already incorporated the change into first sample. Also remove the code that overrides viewDidLayoutSubviews
.
Then, you need to change the initializer of your NewsView
.
Now it looks like this:
-(id) initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if(self) {
[[NSBundle mainBundle] loadNibNamed:@"NewsSection" owner:self options:nil];
[self addSubview:self.view];
}
return self;
}
One problem is here is that you load the nib but don't assign the view from the nib to your view object. The reference (https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/NSBundle_UIKitAdditions/index.html) depicts that loadNibNamed:owner:options:
returns all top level objects. Since we have one top level object in our xib we need to assign this to ourself. This is somewhat hacky and introduces the problem that the nib will leak in the future. So better make a UIViewController with XIB here.
To make your code work, the initializer of NewsView
should look like this. But it won't connect your outlet.
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self = [[NSBundle mainBundle] loadNibNamed:@"NewsSection" owner:self options:nil][0];
}
return self;
}
Upvotes: 1
Reputation: 131426
It's a bit hard to tell what needs to be done from the outside.
Some things you will very likely need to do:
Set translatesAutoresizingMaskIntoConstraints on your view to NO so it doesn't create a whole new set of constraints that conflict with the constraints on your existing view hierarchy.
Add constraints to your newly added view in code that anchor it into your new view hierarchy. You have to add the constraints AFTER you add it as a subview. You will probably need to set a leading edge and a top constraint, and then either height and width or trailing and bottom constraints.
You'll probably want to use the method
+ constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:
Upvotes: 0