I have 2 view controllers embedded in a view vertically. View controller A (uploader), and B (docList).
B contains a UICollectionView
All, methods except cellForItemAtIndexPath inside the datasource of the collection view get called correctly, and i double checked everything. There is 1 section. There are more than 0 rows. The size of the rows I return is smaller than the collection view, etc
Here's a diagram to illustrate the setup:
My issue is:
Unless i turn on setTranslatesAutoresizingMaskIntoConstraints to YES, cellForItemAtIndexPath will never be called. If i set that property to YES on the View Controller B's view, then it does get called. But the layout is then screwed up, because I am not using springs and struts. We only use constraints here.
Do you know what i can be doing wrong when embedding the view controller that contains the UICollectionView?
Here is the code that embeds the two view controllers' views, and sets them as child controllers:
- (MFFormBaseCell *)cellForComponent
{
self.cell = [[MFFormBaseCell alloc] initWithFrame:CGRectZero];
[self.cell addSubview: uploader.view];
[self.cell addSubview: docList.view];
UIView* uploaderView = uploader.view;
UIView* docListView = docList.view;
NSMutableArray* tempConstraints = [[NSMutableArray alloc]init];
[tempConstraints addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat: #"V:|-8-[uploaderView]-1-[docListView]-8-|"
options: NSLayoutFormatDirectionLeadingToTrailing metrics:nil
views: NSDictionaryOfVariableBindings(uploaderView, docListView)]];
[tempConstraints addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat: #"H:|-[uploaderView]-|"
options: NSLayoutFormatDirectionLeadingToTrailing metrics:nil
views: NSDictionaryOfVariableBindings(uploaderView)]];
[tempConstraints addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat: #"H:|-[docListView]|"
options: NSLayoutFormatDirectionLeadingToTrailing metrics:nil
views: NSDictionaryOfVariableBindings(docListView)]];
uploaderConstraints = [tempConstraints copy];
[self.cell addConstraints: uploaderConstraints];
[self.embedder addChildViewController:uploader];
[uploader didMoveToParentViewController:self.embedder];
[self.embedder addChildViewController:docList];
[docList didMoveToParentViewController:self.embedder];
docList.view.frame = self.cell.bounds;
return self.cell;
}
And here is the code from View Controller B, that sets up the UICollectionView and a vertical flow layout for it.
- (void)modelDidLoad
{
_dataSource = [[MFCardDataSource alloc] initWithData: self.cardModel];;
UICollectionViewFlowLayout *aFlowLayout = [[UICollectionViewFlowLayout alloc] init];
[aFlowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
_collectionView = [[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:aFlowLayout];
[_collectionView setDelegate: self];
[_collectionView setDataSource:_dataSource];
[_collectionView setBackgroundColor:[UIColor clearColor]];
for (NSString* type in [MFCardCollectionModel typeArray])
[_collectionView registerClass:[MFImageCard class] forCellWithReuseIdentifier: type];
[_collectionView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:_collectionView];
[self registerConstraintsForView:_collectionView];
if ([self respondsToSelector:#selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
[super modelDidLoad];
}
And the contents of registerConstraintsForView:
-(void) registerConstraintsForView:(UIView*)collectionView
{
NSDictionary* metrics = #{ #"padding": #PADDING };
NSDictionary* views = NSDictionaryOfVariableBindings(_collectionView);
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"V:|-padding-[_collectionView]-padding-|"
options:NSLayoutFormatDirectionLeadingToTrailing
metrics:metrics
views:views]];
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"H:|-padding-[_collectionView]-padding-|"
options:NSLayoutFormatDirectionLeadingToTrailing
metrics:metrics
views:views]];
}
I got around the problem by Subclassing UICollectionView, and using the subclass instead.
On the subclass I overrode 2 methods:
- (void) setContentSize:(CGSize)contentSize
{
CGSize origSize = self.contentSize;
[super setContentSize:contentSize];
if (!CGSizeEqualToSize(contentSize, origSize))
{
[self invalidateIntrinsicContentSize];
}
}
- (CGSize) intrinsicContentSize
{
return CGSizeMake(UIViewNoIntrinsicMetric, self.contentSize.height);
}
Then, i have a method inside my view controller which contains the Collection View, which calculates the required Height needed for the collection view.
I then call setContentSize with the calculated height on my subclass of Collection View, and that makes sure that it returns an intrinsicContentSize as tall as it needs to be to show all the card records inside it.
Related
self.refreshControl = [[UIRefreshControl alloc]init];
[self.objDiscussiontopic addSubview:self.refreshControl];
[self.refreshControl addTarget:self action:#selector(refreshTable) forControlEvents:UIControlEventValueChanged];
- (void)refreshTable {
//TODO: refresh your data
[self.refreshControl endRefreshing];
}
This is the code i am using to add refresh controller in my scroll view.
But when i pull down the scroll view the refresh control is not showing and the targeted method is also not called why ?
I am searching this for a while but didn't get any proper answer .
One more thing scrollview having VFL Constraint some thing like this :
//Pin scrolview to Parent View
[VFLConstraint allignSubViewViewHorizentallyWithSubView:self.objDiscussiontopic OverSuperView:[self view]];
[VFLConstraint allignSubViewViewVerticallyWithSubView:self.objDiscussiontopic OverSuperView:[self view] WithTopPading:[CommonFunction convertIphone6ToIphone5:0] AndBotomPading:[CommonFunction convertIphone6ToIphone5:57]];
+ (void)allignSubViewViewHorizentallyWithSubView:(UIView *)subView OverSuperView:(UIView *)superView{
NSDictionary *viewDict= NSDictionaryOfVariableBindings(subView);
[superView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[subView]|" options:0 metrics: 0 views:viewDict]];
}
+ (void)allignSubViewViewVerticallyWithSubView:(UIView *)subView OverSuperView:(UIView *)superView WithTopPading:(float)topPading AndBotomPading:(float)bottomPading{
NSDictionary *viewDict= NSDictionaryOfVariableBindings(subView);
NSDictionary *metrics=[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithFloat:topPading],#"topPading",[NSNumber numberWithFloat:bottomPading],#"bottomPading", nil];
[superView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-topPading-[subView]-bottomPading-|" options:0 metrics: metrics views:viewDict]];
}
Try to:
[self.scrollView insertSubview:self.refreshControl atIndex:0];
Check the contentSize it can be less that frame size, if so use this line of code:
self.scrollView.alwaysBounceVertical = true
I don't think a UIRefreshControl is designed to work with plain scroll views. Apple's docs specifically refer to UITableViews when talking about refresh control.
You can look at third party pull to refresh libraries to add this to UIScrollView
I have the following UIView hierarchy:
-UIView
-UIScrollView
My constraint for UIScrollview with relation to it's super view are very simple:
#"H:|-%f-[%#]-%f-|"
and
#"V:|-%f-[%#]-%f-|"
They are working as expected.
I am trying to add a UIImageView as subview of scrollview Horizontal.
So my view hierarchy will become:
-UIView
-UIScrollView
-UIImageView
I am adding UIImageView as subview programmatically in UIScrollView using a for loop.
In the for loop, how can I achieve:
[SuperView]-10-[scrollview]-10-[UIImageView]-10-[UIImageView]-10-[UIScrollView]-10-[SuperView]
The problematic section is the bold part.
What I have tried:
for(int i=1;i<3;i++)
{
UIImageView *image = [[UIImageView alloc] init];
[image setImage:[UIImage imageNamed:[NSString stringWithFormat:#"%d.jpg",i]]];
image.translatesAutoresizingMaskIntoConstraints = NO;
[_scrollView addSubview:image];
UIView *superView = _scrollView;
NSDictionary * views = NSDictionaryOfVariableBindings(superView, image);
NSString *formate = [NSString stringWithFormat:#"H:|-%f-[%#]-%f-|", scrollViewLeftMarginFromParent, #"image", scrollViewRightMarginFromParent];
NSArray * WIDTH_CONSTRAINT = [NSLayoutConstraint constraintsWithVisualFormat:formate options:0 metrics:nil views:views];
formate = [NSString stringWithFormat:#"V:|-%f-[%#]-%f-|", scrollViewTopMarginFromParent, #"image", scrollViewBottomMarginFromParent];
NSArray * HEIGHT_CONSTRAINT = [NSLayoutConstraint constraintsWithVisualFormat:formate options:0 metrics:nil views:views];
[superView addConstraints:WIDTH_CONSTRAINT];
[superView addConstraints:HEIGHT_CONSTRAINT];
}
The approach I can think of:
LeftSide:
[scrollview]-10-[UIImageView]
Right side:
[UIImageView]-10-[scrollview]
in between:
[UIImageView]-10-[UIImageView]
If it's the right approach, then how do I achieve this in for loop.
If it's not then what is best approach.
It's quite simple actually. Your approach is correct, all you need is how you convert that into code. I will try to simplify this for you. I am assuming a UIImageView's width & height as 100. You can change as you like
-(void)setUI
{
lastView = nil; //Declare a UIImageView* as instance var.
arrayCount = [array count]; //In your case a static count of 3
for(NSInteger index =0; index < arrayCount; index++)
{
UIImageView *view = [[UIImageView alloc] init];
[self.mainScroll addSubview:view];
[view setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.mainScroll addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-20-[view(100)]-20-|" options:0 metrics:nil views:#{#"view":view}]];
//--> If view is first then pin the leading edge to main ScrollView otherwise to the last View.
if(lastView == nil && index == 0) {
[self.mainScroll addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-10-[view(100)]" options:0 metrics:nil views:#{#"view":view}]];
}
else {
[self.mainScroll addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:[lastView]-10-[view(100)]" options:0 metrics:nil views:#{#"lastView":lastView, #"view":view}]];
}
//--> If View is last then pin the trailing edge to mainScrollView trailing edge.
if(index == arrayCount-1) {
[self.mainScroll addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:[view]-10-|" options:0 metrics:nil views:#{#"view":view}]];
}
//--> Assign the current View as last view to keep the reference for next View.
lastView = view;
}
}
I had encountered similar situation where my scrollview along with its content view was created from IB, but the subviews were added programatically. Writing constraints for subviews was making the View controller bloated. Also the for loop was was getting a lots of ifs and elses,hence I wrote a UIView Subclass to handle this scenario.
Change the class type for you Content View in IB, get a reference of it, add subviews through directly setting the property stackViewItems,or methods -(void)insertStackItem:, -(void)insertStackItem:atIndex:
#import "IEScrollContentView.h"
#interface IEScrollContentView()
{
NSMutableArray * _stackViewItems;
}
#property (nonatomic,strong) NSLayoutConstraint * topConstraint;
#property (nonatomic,strong) NSLayoutConstraint * bottomConstraint;
#end
#implementation IEScrollContentView
#synthesize stackViewItems = _stackViewItems;
//-----------------------------------------------------------------//
#pragma mark - Init Methods
//-----------------------------------------------------------------//
-(instancetype)initWithCoder:(NSCoder *)aDecoder {
if(self = [super initWithCoder:aDecoder])
_stackViewItems = [NSMutableArray new];
return self;
}
-(instancetype)initWithFrame:(CGRect)frame {
if(self = [super initWithFrame:frame])
_stackViewItems = [NSMutableArray new];
return self;
}
//-----------------------------------------------------------------//
#pragma mark - Public Methods
//-----------------------------------------------------------------//
-(void)setStackViewItems:(NSArray *)stackViewItems {
if(!_stackViewItems)
_stackViewItems = [NSMutableArray new];
for (UIView * view in stackViewItems) {
[self insertStackItem:view];
}
}
-(void)insertStackItem:(UIView *)stackItem
{
[self insertStackItem:stackItem atIndex:_stackViewItems.count];
}
-(void)insertStackItem:(UIView *)stackItem atIndex:(NSUInteger)index
{
if(!stackItem || index > _stackViewItems.count)return;
if(index == 0)
[self addView:stackItem
belowView:self
aboveView:_stackViewItems.count>0?_stackViewItems.firstObject:self];
else if(index==_stackViewItems.count)
[self addView:stackItem
belowView:_stackViewItems[index-1]
aboveView:self];
else
[self addView:stackItem
belowView:_stackViewItems[index-1]
aboveView:_stackViewItems[index]];
}
//-----------------------------------------------------------------//
#pragma mark - Constraining Views
//-----------------------------------------------------------------//
-(void)addView:(UIView *)view belowView:(UIView *)viewAbove aboveView:(UIView *)viewBelow {
view.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:view];
NSArray * defaultConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[view]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)];
NSLayoutConstraint * upperConstraint,* lowerConstraint;
if(viewAbove==self) {
[self removeConstraint:_topConstraint];
upperConstraint = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[view]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)].firstObject;
_topConstraint = upperConstraint;
}
else
upperConstraint = [NSLayoutConstraint constraintsWithVisualFormat:#"V:[viewAbove]-0-[view]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view,viewAbove)].firstObject;
if(viewBelow==self) {
[self removeConstraint:_bottomConstraint];
lowerConstraint = [NSLayoutConstraint constraintsWithVisualFormat:#"V:[view]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)].firstObject;
_bottomConstraint = lowerConstraint;
}
else
lowerConstraint = [NSLayoutConstraint constraintsWithVisualFormat:#"V:[view]-0-[viewBelow]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view,viewBelow)].firstObject;
[self addConstraints:defaultConstraints];
[self addConstraints:#[upperConstraint,lowerConstraint]];
[_stackViewItems addObject:view];
}
#end
I have uploaded the files here
IEScrollContentView.h
IEScrollContentView.h.m
I'm working on a project that must support both iOS 8 and iOS 7.1. Right now I'm running into a problem that only appears on iOS 7.1 but works properly on iOS 8. I have a ViewController that contains a tableview and a custom view in the tableHeaderView. I'll post the code as follows. All constraints are added programatically.
//View Controller.
-(void)viewDidLoad
{
[super viewDidLoad];
self.commentsArray = [NSMutableArray new];
[self.commentsArray addObject:#"TEST"];
[self.commentsArray addObject:#"TEST"];
[self.commentsArray addObject:#"TEST"];
[self.commentsArray addObject:#"TEST"];
[self.commentsArray addObject:#"TEST"];
[self.commentsArray addObject:#"TEST"];
[self.view addSubview:self.masterTableView];
self.masterTableView.tableHeaderView = self.detailsView;
[self.view setNeedsUpdateConstraints];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.view layoutIfNeeded];
}
//Table view getter
- (UITableView *)masterTableView
{
if(!_masterTableView)
{
_masterTableView = [UITableView new];
_masterTableView.translatesAutoresizingMaskIntoConstraints = NO;
_masterTableView.backgroundColor = [UIColor greyColor];
_masterTableView.delegate = self;
_masterTableView.dataSource = self;
_masterTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
_masterTableView.showsVerticalScrollIndicator = NO;
_masterTableView.separatorInset = UIEdgeInsetsZero;
}
return _masterTableView;
}
-(void)updateViewConstraints
{
NSDictionary *views = #{
#"table" : self.masterTableView,
#"details" : self.detailsView,
};
NSDictionary *metrics = #{
#"width" : #([UIScreen mainScreen].applicationFrame.size.width)
};
//Table view constraints
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[table]-0-|" options:0 metrics:0 views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[table]-0-|" options:0 metrics:0 views:views]];
//Details View
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[details(width)]-0-|" options:0 metrics:metrics views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[details]-0-|" options:0 metrics:metrics views:views]];
}
//Details View Getter
- (DetailsView *)detailsView
{
if(!_detailsView)
{
_detailsView = [[DetailsView alloc]initWithFrame:CGRectMake(0, 0, 0, 100)];
_detailsView.backgroundColor = [UIColor orangeColor];
return _detailsView;
}
Now the details view contains some basic subviews which all derive from a UIView and the details view itself derives from a more general super class. I'll post the code as follows.
//Parent View
#interface ParentView (): UIView
- (instancetype)init
{
self = [super init];
if (self)
{
[self setupViews];
}
return self;
}
- (void)setupViews
{
[self addSubview:self.publishedTimeView];
}
- (void)updateConstraints
{
NSDictionary *views = #{
#"time" : self.publishedTimeView,
};
// Header with published video time
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:[time]-10-|" options:0 metrics:0 views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[time(11)]" options:0 metrics:0 views:views]];
[super updateConstraints];
}
//Getter for the timePublished view added to the detail view. Will not post all its related code for //the sake of brevity.
- (TimePublishedDetailView *)publishedTimeView
{
if(!_publishedTimeView)
{
_publishedTimeView = [TimePublishedDetailView new];
_publishedTimeView.translatesAutoresizingMaskIntoConstraints = NO;
}
return _publishedTimeView;
}
//Child View (or the detailsView) of the view controller.
#interface DetailsView : ParentView
#implementation RecordingDetailsView
- (void)updateConstraints
{
NSDictionary *views = #{
#"time" : self.publishedTimeView,
};
//Vertical alignment of all views
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-20-[time]" options:0 metrics:nil views:views]];
[super updateConstraints];
}
- (void)setModel:(DetailViewModel *)model
{
self.publishedTimeView.date = model.dateTime;
[self setNeedsUpdateConstraints];
[self layoutSubviews];
}
Now on iOS 8 this looks like this:
However on iOS 7.1 this will crash with this error message:
"Exception: Auto layout still required after executing -layoutSubviews. UITableView's implementation of -layoutSubviews needs to call super"
I've googled this and played around with the code in my layout calls to see if I can remedy the problem but so far have been unsuccessful. If anyone could post some tips or advice on how to fix this I would really appreciate it.
I know this question is old, but I ran into a similar problem recently and after a lot of Googling, trying and failing I made it work with the help of this answer and a few changes.
Just add this category to your project and call [UITableView fixLayoutSubviewsMethod]; only once (I recommend inside AppDelegate).
#import <objc/runtime.h>
#import <objc/message.h>
#implementation UITableView (FixUITableViewAutolayoutIHope)
+ (void)fixLayoutSubviewsMethod
{
Method existing = class_getInstanceMethod(self, #selector(layoutSubviews));
Method new = class_getInstanceMethod(self, #selector(_autolayout_replacementLayoutSubviews));
method_exchangeImplementations(existing, new);
}
- (void)_autolayout_replacementLayoutSubviews
{
[super layoutSubviews];
[self _autolayout_replacementLayoutSubviews]; // not recursive due to method swizzling
[super layoutSubviews];
}
#end
I have a UICollectionView inside of a UITableViewCell, and the CollectionView cells show images that a user stores in the app. When the user taps the cell, the image is presented full screen. So I created a UIViewController, added a UIScrollView to it for zooming, then added a UIImageView to the ScrollView. Everything works nicely until the user changes the orientation of the phone. When they change to landscape the view adjusts but the scrollview and image view do not adjust, and therefore just show on the left side of the screen; they seem to keep the same bounds. I tried to fix this by following apple's tech note using the pure layout approach and adding constraints. But when I do this, the image that is displayed is zoomed all the way in and I cannot get it to fit correctly. When I use an NSLog statement to determine the frames, they are all set to self.view.frame and therefore printout the size of the screen, but the image still shows at full size. Everything is created programmatically, no xib files.
I would love to avoid the constraints, but they seem necessary for the user to be able to see images correctly in landscape mode. I have tried setting the contentSize of the scrollview, setting clipsToBounds to YES and changing the contentMode but none of these things have any effect. Any help is greatly appreciated!
collectionView:didSelectItemAtIndexPath:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary *viewsDictionary;
//creating ViewController to be presented
UIViewController *fullImageView = [[UIViewController alloc] init];
fullImageView.view.userInteractionEnabled = YES;
fullImageView.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[[UIApplication sharedApplication] setStatusBarHidden:YES];
_selectedImageView = [[UIImageView alloc] initWithFrame:self.view.frame];
NSString *key = [self.viewItem.imageKeyArray objectAtIndex:indexPath.row];
_selectedImageView.image = [self.viewItem.itemImages objectForKey:key];
_selectedImageView.clipsToBounds = YES;
_selectedImageView.contentMode = UIViewContentModeScaleAspectFit;
_selectedImageView.translatesAutoresizingMaskIntoConstraints = NO;
UIScrollView *imageScrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
imageScrollView.delegate = self;
imageScrollView.minimumZoomScale = 1;
imageScrollView.maximumZoomScale = 2;
imageScrollView.translatesAutoresizingMaskIntoConstraints = NO;
[fullImageView.view addSubview:imageScrollView];
[imageScrollView addSubview:_selectedImageView];
viewsDictionary = NSDictionaryOfVariableBindings(imageScrollView, _selectedImageView);
[fullImageView.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[imageScrollView]|" options:0 metrics: 0 views:viewsDictionary]];
[fullImageView.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[imageScrollView]|" options:0 metrics: 0 views:viewsDictionary]];
[imageScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[_selectedImageView]|" options:0 metrics: 0 views:viewsDictionary]];
[imageScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[_selectedImageView]|" options:0 metrics: 0 views:viewsDictionary]];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissFullImageView)];
[fullImageView.view addGestureRecognizer:tap];
[self presentViewController:fullImageView animated:YES completion:nil];
}
I have a problem with a custom view and autolayout. To make things simple I will use two UILabels, the first one should change its background color when the device rotate. The problem is that it doesn't do it! Any hint?
Thanks!
Nicola
- (id)init
{
self = [super init];
if (self) {
//Add the subviews to the mainView
[self.view addSubview:self.label1];
[self.view addSubview:self.label2];
//Autolayout
//Create the views dictionary
NSDictionary *viewsDictionary = #{#"header":self.label1,
#"table": self.label2};
//Create the constraints using the visual language format
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat: #"H:|[header]|"
options:0
metrics:nil
views:viewsDictionary]];
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat: #"H:|[table]|"
options:0
metrics:nil
views:viewsDictionary]];
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"V:|[header(==50)][table]|"
options:0
metrics:nil
views:viewsDictionary]];
}
return self;
}
-(UIView*) label1
{
_label1 = [UILabel alloc] init];
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)){
_label1.backgroundColor = [UIColor redColor];
}else{
_label1.backgroundColor = [UIColor greenColor];
}
_label1.translatesAutoresizingMaskIntoConstraints=NO;
return _label1;
}
-(UIView*) label2
{
_label2 = [UILabel alloc] init];
_label2.backgroundColor = [UIColor yellowColor];
_label2.translatesAutoresizingMaskIntoConstraints=NO;
_return label2;
}
-(BOOL) shouldAutorotate
{
return YES;
}
-(NSUInteger) supportedInterfaceOrientations
{
if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad){
//I am on a pad
return UIInterfaceOrientationMaskAll;
} else {
//I am on a Phone
return UIInterfaceOrientationMaskAllButUpsideDown;
}
}
-(void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
//I expect the label1 to change its background color
[self.view setNeedDisplay];
}
If you move the code related to [self.label1 setBackgroundColor:] to the delegate method didRotateFromInterfaceOrientation:, it should work better. Also, in your custom getters, you are allocating a new label every time you access the method. In most situations it's preferable to check if the ivar is not nil at the beginning, and returning the ivar, instead for allocating a fresh label.