Setting a label to UITableView's tableFooterView - with autolayout - objective-c

When my table view is empty, I want to add a simple label into the tableview footer to display a "no content" message. It was working fine when I was setting the frames of the UILabel and the UIView that I used for footerView, but now I'm trying to convert to using auto-layout, and I can't get it to work.
Here's what I'm doing:
// Create the footer
UIView *tempFooter = [[UIView alloc] init];
UILabel *atext = [[UILabel alloc] init];
tempFooter.translatesAutoresizingMaskIntoConstraints = NO;
atext.translatesAutoresizingMaskIntoConstraints = NO;
atext.numberOfLines = 0;
[atext setText:#"Add Some Text"];
atext.textAlignment = NSTextAlignmentCenter;
atext.font = [UIFont italicSystemFontOfSize:14];
atext.textColor = [UIColor grayColor];
atext.backgroundColor = [UIColor clearColor];
atext.lineBreakMode = NSLineBreakByWordWrapping;
// add label to footer view, and add constraints
[tempFooter addSubview:atext];
NSLayoutConstraint *tvatt1 = [NSLayoutConstraint constraintWithItem:tempFooter
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:atext attribute:NSLayoutAttributeLeft
multiplier:1.0
constant:10.0];
NSLayoutConstraint *tvatt2 = [NSLayoutConstraint constraintWithItem:tempFooter
attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationEqual
toItem:atext
attribute:NSLayoutAttributeRight
multiplier:1.0
constant:10.0];
NSLayoutConstraint *tvatt3 = [NSLayoutConstraint constraintWithItem:tempFooter
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:atext
attribute:NSLayoutAttributeTop
multiplier:5.0
constant:0];
NSLayoutConstraint *tvatt4 = [NSLayoutConstraint constraintWithItem:tempFooter
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:atext
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant: 0];
[tempFooter addConstraints: #[tvatt1, tvatt2, tvatt3, tvatt4]];
// set the footerview
self.tview.tableFooterView = tempFooter;
When I run this, I get a crash:
2014-09-08 19:57:16.594 SimpleList[49442:60b] * Assertion failure in
-[UITableView layoutSublayersOfLayer:], /SourceCache/UIKit_Sim/UIKit-2935.137/UIView.m:8794 2014-09-08
19:57:21.073 SimpleList[49442:60b] * Terminating app due to uncaught
exception 'NSInternalInconsistencyException', reason: 'Auto Layout
still required after executing -layoutSubviews. UITableView's
implementation of -layoutSubviews needs to call super
I'm not sure what I'm doing wrong. I've also tried setting constraints for the self.tview.tableFooterView wrt the tempFooter (pinning against all 4 sides) but that doesn't change the crash. I also call:
[self.tview.tableFooterView layoutSubviews];
but that doesn't help either.
Any ideas what I'm doing wrong?

You shouldn't set translatesAutoresizingMaskIntoConstraints to NO for table views, their cells, or table header and footer views (or for your controller's self.view for that matter). It's ok to use constraints for views inside those views (the content view of cells or the header and footer views). I added a simplified version of your code to viewDidLoad, and it worked as expected. Note that you need to give the footer view a height and an x position (the y position and the width are ignored),
UIView *tempFooter = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 50)];
UILabel *atext = [[UILabel alloc] init];
atext.translatesAutoresizingMaskIntoConstraints = NO;
atext.numberOfLines = 0;
[atext setText:#"Add Some Text"];
atext.textAlignment = NSTextAlignmentCenter;
atext.font = [UIFont italicSystemFontOfSize:14];
atext.textColor = [UIColor grayColor];
atext.backgroundColor = [UIColor clearColor];
atext.lineBreakMode = NSLineBreakByWordWrapping;
[tempFooter addSubview:atext];
NSDictionary *dict = NSDictionaryOfVariableBindings(atext);
[tempFooter addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"|-10-[atext]-10-|" options:0 metrics:nil views:dict]];
[tempFooter addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[atext]|" options:0 metrics:nil views:dict]];
self.tableView.tableFooterView = tempFooter;
I'm not sure what you were trying to accomplish with your constraint, tvatt3. The multiplier (you have 5) doesn't do anything with a top or left constraint since the value of those attributes is 0. I used the visual constraints, rather than the method you used, but when I used your code to add the constraints, it worked also .

Interestingly, changing the Autoresizing mask in the xib solved my problem.
Constraints not working:
Working:

I was able to make dynamically auto layout table footer width and height by implementing #rdelmar solution for constraints and adding these lines below. Same solution applies to table header view.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let tableFooter = tableView.tableFooterView {
let maxSize = CGSize(width: self.tableView.bounds.size.width,
height: CGFloat.greatestFiniteMagnitude)
let size = tableFooter.systemLayoutSizeFitting(maxSize)
let height = size.height
var headerFrame = tableFooter.frame
// If we don't have this check, viewDidLayoutSubviews() will get
// repeatedly, causing the app to hang.
if height != headerFrame.size.height {
headerFrame.size.height = height
tableFooter.frame = headerFrame
tableView.tableFooterView = tableFooter
}
}
}
P. S. I prefer Interface Builder for constraints setup

hope this will help you
I am not sure of this but it help me in my project, first add every thing in contentView (all the subview and the constraint)
[self.contentView addSubview:atext]
and then comes to code part
NSLayoutConstraint *tvatt1 = [NSLayoutConstraint constraintWithItem:tempFooter
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:atext attribute:NSLayoutAttributeLeft
multiplier:1.0
constant:10.0];
code saying for left attribute
temfooter(must be equal) = 1.0*atext +10.0
i.e
temfooter must be equal to the modified atext , so need to make sure that your constraints are not wrong.

Related

Programmatically created NSTableView within NSScroll view cannot scroll horizontally

I am on macOS 10.16 (BigSur) XCode 12, objective-c.
I have create a NSTableView within an NSScroll View programmatically and filled it with dummy data.
I CAN scroll down while i CANNOT scroll left and right. So i assume there's some misconfiguration in the code but i can't figure it out.
Here's the behaviour -as you can see theres more content on the right, but scrollbar doesn't scroll:
And here's the code:
NSEdgeInsets insets = NSEdgeInsetsMake (0,0,0,0); // This is usually dynamic, just for demo purposes
NSEdgeInsets margins = NSEdgeInsetsMake (0,0,0,0); // This is usually dynamic, just for demo purposes
// Create tableView
NSTableView* tableView = [[NSTableView alloc] initWithFrame:NSZeroRect];
tableView.translatesAutoresizingMaskIntoConstraints = NO;
tableView.backgroundColor = [NSColor clearColor];
tableView.delegate = self.delegate ? self.delegate : weakSelf;
tableView.dataSource = self.delegate ? self.delegate : weakSelf;
tableView.rowHeight = [SHDataTableCellView height];
tableView.intercellSpacing = NSMakeSize(2, 2);
tableView.headerView = [[NSTableHeaderView alloc] initWithFrame:NSMakeRect(0, 0, 0, CGFLOAT_MIN)];
if (#available(macOS 11.0, *)) {tableView.style = NSTableViewStylePlain;}
self.tableView = tableView;
// Create Scroll View
NSScrollView* scrollView = [[NSScrollView alloc] initWithFrame:NSZeroRect];
// Setup scrollView
scrollView.drawsBackground = NO;
scrollView.hasVerticalScroller = YES;
scrollView.hasHorizontalScroller = YES;
scrollView.autohidesScrollers = NO;
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
scrollView.documentView = tableView;
scrollView.scrollerStyle = NSScrollerKnobStyleDefault;
scrollView.automaticallyAdjustsContentInsets = NO;
scrollView.contentInsets = insets;
scrollView.scrollerInsets = NSEdgeInsetsMake(-(insets.top), -(insets.left), -(insets.bottom), -(insets.right));
self.scrollView = scrollView;
[self.view addSubview:scrollView];
// Add constraints
NSDictionary *viewBindings = NSDictionaryOfVariableBindings(view,scrollView);
NSDictionary *metrics = #{ #"marginLeft" : #(margins.left),
#"marginRight" : #(margins.right),
#"marginBottom" : #(margins.bottom),
#"marginTop" : #(margins.top),
#"insetLeft" : #(insets.left),
#"insetRight" : #(insets.right),
#"insetBottom" : #(insets.bottom),
#"insetTop" : #(insets.top)};
[view addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:#"H:|-(marginLeft)-[scrollView]-(marginRight)-|" options:0 metrics:metrics views:viewBindings]];
[view addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:#"V:|-(marginTop)-[scrollView]-(marginBottom)-|" options:0 metrics:metrics views:viewBindings]];
[scrollView addConstraint:[NSLayoutConstraint constraintWithItem:self.tableView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:scrollView
attribute:NSLayoutAttributeWidth
multiplier:1.0
constant:0]];
[scrollView addConstraint:[NSLayoutConstraint constraintWithItem:scrollView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:60]]; // equals 2 rows of content
NSEdgeInsets margin and insets are set to 0 in this example are tend to be used as dynamic variables (you may ignore them)
Removed the width constraint and it worked. Sometimes its just too obvious and you still don't see it.

Why my constraints doesn't work in my xib file

I am trying to add a button to a UIstackview, programmatically. All this is in fitxero XIB.
  The button is created correctly, but when adding the constraints I get the following error:
2020-05-21 17:51:08.328369+0200 eWAS[3391:567586] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view?
That's illegal. constraint: < NSLayoutConstraint:0x282362b70 V:|-(0)-[UIButton:0x11c225a60'button'] (active, names: '|':UIStackView:0x11bfc13f0 ) > view:< UIButton: 0x11c225a60; frame = (0 0; 30 150); opaque = NO; layer = < CALayer: 0x2802e4220 > >'
-(void) configureTabsWithTexts: (NSArray *) tabs{
NSInteger tag = 0;
UIButton *currentButton = [UIButton buttonWithType:UIButtonTypeSystem];
[currentButton setTitle:#"Button1" forState:UIControlStateNormal];
[currentButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[currentButton setTag:tag];
[currentButton.titleLabel setFont:[UIFont systemFontOfSize:20]];
[currentButton.titleLabel setTextColor:[UIColor whiteColor]];
[currentButton setFrame:CGRectMake(0, 0, 30, 150)];
currentButton.backgroundColor = [UIColor blackColor];
[self.stackViewForButtons addSubview:currentButton];
[currentButton setTranslatesAutoresizingMaskIntoConstraints:NO];
NSMutableArray <NSLayoutConstraint *> *arrayConstraints = [[NSMutableArray alloc] init];
currentButton.translatesAutoresizingMaskIntoConstraints = false;
[currentButton addSubview:self.stackViewForButtons];
[currentButton addConstraint: [NSLayoutConstraint constraintWithItem:currentButton
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.stackViewForButtons
attribute:NSLayoutAttributeTop
multiplier:1
constant:0]];
[currentButton addConstraint: [NSLayoutConstraint constraintWithItem:currentButton
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:currentButton.superview
attribute:NSLayoutAttributeBottom
multiplier:1
constant:0]];
[currentButton addConstraint: [NSLayoutConstraint constraintWithItem:currentButton
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:50]];
[currentButton addConstraint: [NSLayoutConstraint constraintWithItem:currentButton
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:currentButton.superview
attribute:NSLayoutAttributeLeading
multiplier:1
constant:0]];
}
You have this line:
[self.stackViewForButtons addSubview:currentButton];
which seems fine, but then later you are doing:
[currentButton addSubview:self.stackViewForButtons];
which seems backwards and is probably the source of your problem. Try removing that latter line and see if it works. I doubt you want a UIButton to have a stack view as a subview. With both lines in place, there is a circular reference, which UIView probably figures out and removes the original superview of the UIButton, meaning that is nil when you are creating the later constraints (or maybe it removes the superview/subview relationship altogether).
As an aside, if you are using an actual UIStackView which it looks like you are, you shouldn't need any of these constraints done by hand. The entire point of UIStackView is to generate all those constraints for you. In that case, simply call:
[self.stackViewForButtons addArrangedSubview:currentButton];
[currentButton setTranslatesAutoresizingMaskIntoConstraints:NO];
and you should be done, provided you have configured the stack view correctly. Maybe you need the width constraint on each one, not sure. While you can add non-arranged subviews to a UIStackView, that should be rare. And even if that is intended in this case, you may be better off adding another UIStackView as a subview, then adding the buttons to that.

How can I disable horizontal scrolling and page will change on click in paging using UIScrollView?

I have a UIScrollView with pagingEnabled. Added 5 UIStackView to subview of UIScrollView and also had one UISegmentedControl. I want to show currently selected segment and also want to disable horizontal scrolling but the view will able to scroll vertically.
let take an example:
Let selected page index = 0
User not able to scroll or drag horizontally to navigate to next page.
The user can scroll vertically
Now User selected page index = 1 in UISegmentedControl
2nd page will be visible
Now user not able to scroll or drag to 0 and 2 index
How can I achieve this functionality using UIScrollView
Tried logic:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
CGFloat xOff = self.scrollView.frame.size.width * self.currentPage;
[self.scrollView setContentSize:CGSizeMake(xOff, self.scrollView.contentSize.height)];
//[self.scrollView setContentOffset:CGPointMake(xOff, 0) animated:true];
}
but using this UIScrollView after changing page When I scroll again go to 0 page.
You can use UICollectionView with paging enabled and inside you can implement UIScrollView with vertical scroll enable. Disable the UICollectionView scroll and change the index collection cell on click using below code:
accepted
New, Edited Answer:
Add this in viewDidLayoutSubviews
SWIFT
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let indexPath = IndexPath(item: 12, section: 0)
self.collectionView.scrollToItem(at: indexPath, at: [ .centeredHorizontally], animated: true)
}
Normally, .centerVertically is the case
Objective-C
-(void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:12 inSection:0];
[self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
}
I am using this solution from my own question
In segmentDidChange() method
[self.scrollView.subviews makeObjectsPerformSelector: #selector(removeFromSuperview)];
self.scrollView.showsVerticalScrollIndicator = false;
self.scrollView.showsHorizontalScrollIndicator = false;
self.arrSubViews = [NSMutableArray array];
// Loading view's from xib's
// Now
UIView *containerView = [[UIView alloc]initWithFrame:self.scrollView.frame];
containerView.translatesAutoresizingMaskIntoConstraints = false;
[self prepareStackViewforPage:index withContainerView:containerView];
Now preparing stackView for selected index
- (void)prepareStackViewforPage:(NSInteger)index withContainerView:(UIView *)containerView {
[self.scrollView addSubview:containerView];
[self applyConstraintsToParent:self.scrollView andSubView:containerView];
UIStackView *stackView = [[UIStackView alloc] initWithArrangedSubviews:self.arrSubViews];
[stackView setFrame:self.scrollView.frame];
stackView.translatesAutoresizingMaskIntoConstraints = false;
stackView.axis = UILayoutConstraintAxisVertical;
stackView.spacing = 0;
stackView.distribution = UIStackViewDistributionFill;
stackView.alignment = UIStackViewAlignmentFill;
[containerView addSubview:stackView];
[self applyConstraintsToParent:containerView andSubView:stackView];
[self.view updateConstraintsIfNeeded];
[self.view layoutIfNeeded];
[self.view layoutSubviews];
}
In applyConstraintsToParent:andSubView: method
- (void)applyConstraintsToParent:(UIView *)parentView andSubView:(UIView *)subView {
//constraints
NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0];
[parentView addConstraint:leading];
NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0];
[parentView addConstraint:trailing];
NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
[parentView addConstraint:top];
NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-8];
[parentView addConstraint:bottom];
NSLayoutConstraint *equalWidth = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0];
[parentView addConstraint:equalWidth];
leading.active = true;
trailing.active = true;
top.active = true;
bottom.active = true;
equalWidth.active = true;
}
Now it's just working fine but now I have following issues
View's added via xib height not changing dynamically
I have raised a question for this issue on UIStackView: Loading views from xib and updating height constraint of subView did not reflect any changes?
But this logic working fine in storyboard?
Following your question the answer in to set isScrollEnabled property of UIScrollView to false like following:
For Objective-C
[self.scrollView setScrollEnabled:NO];
For swift
self.scrollView.isScrollEnabled = false
As Apple documentation says about this property:
A Boolean value that determines whether scrolling is enabled.
If the value of this property is true , scrolling is enabled, and if it is false , scrolling is disabled. The default is true.
When scrolling is disabled, the scroll view does not accept touch events; it forwards them up the responder chain.
So your scrollView won't accept touches, but content of your scrollView will.
And this doesn't disallow you to scroll your scrollView programmatically (which is changing contentOffset property of your scrollView). So when selected segment of your UISegmentedControl has changed you should calculate new content offset for your scrollView depending on pages size and set it, I advise you to use setContentOffset(_:animated:) method of UIScrollView to achieve scrolling.
Hope it helps.

NSPopover and adding spacing with NSStatusItem

I am working on a menubar app, that uses NSPopover. I am using the following code to present popover.
[self.mainPopover showRelativeToRect:[testView bounds] ofView:testView preferredEdge:NSMinYEdge];
Issue is this is being present too close to status bar as shown below.
Even if i change the rect it does not have any effect and rightly so, as the documentation states
The rectangle within positioningView relative to which the popover should be positioned. Normally set to the bounds of positioningView. May be an empty rectangle, which will default to the bounds of positioningView.
Following is the screenshot from dropbox app, was just wondering how can i add some spacing in my app like dropbox.
To achieve this i added a padding view and attach set NSStatusItem View to that container view. Code from the solution used is as follow for anybody looking to implement it.
_paddingView = [NSView new];
[_containerView addSubview:_paddingView];
[_containerView addSubview:_dragView];
[_dragView setTranslatesAutoresizingMaskIntoConstraints:NO];
[_paddingView setTranslatesAutoresizingMaskIntoConstraints:NO];
[_containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[_dragView(22)][_paddingView(5)]|" options:0
metrics:nil views:views]];
[_containerView addConstraint:[NSLayoutConstraint constraintWithItem:_dragView
attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual
toItem:_paddingView attribute:NSLayoutAttributeLeft
multiplier:1. constant:0]];
[_containerView addConstraint:[NSLayoutConstraint constraintWithItem:_dragView
attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual
toItem:_paddingView attribute:NSLayoutAttributeRight
multiplier:1. constant:0]];
self.mainPopover = [[NSPopover alloc] init];
self.mainPopover.delegate = self;
self.mainPopover.backgroundColor = [NSColor greenColor];
[self.mainPopover setAnimates:NO];
[self.mainPopover setBehavior:NSPopoverBehaviorTransient];
[self.mainPopover setContentViewController:viewController];
[_containerView layoutSubtreeIfNeeded];
[_statusItem setView:_containerView];
You could inset the test view bounds to add some margin between de view and popover:
NSPopover *mainPopover = [self mainPopover];
NSRect bounds = CGRectInset([testView bounds], -50.0, -50.0);
[mainPopover showRelativeToRect:bounds ofView:testView preferredEdge:NSMinYEdge];

Can't get a UIImageView fill the parent UIView with autolayout

I'm trying to fill a UIView with a UIImageView using auto layout. I've tried several thing, but the most obvious, equalSize with parent view only works when I set the correct size in "Simulated metric". If I let Freeform (the point of autolayout isn't it ?) I get messed up.
I'm testing on an iPhone 4S and a 6 plus.
Thanks for any leading tracks.
EDIT FOR #mittens
I've seen your edit. I still can get it working. As you see I have 4 margin constraints, the same as in your code (I did not need the rest because I only use the main UIView).
Anyway, when I change the size on xcode, the layout is perfect, when I send it to my 4S, I only get Top and left margins.
I'd double check the constraints on the UIView you're trying to fill with the UIImageView to make sure it is filling up its parent view as it should be when the storyboard/xib is set to freeform. Also if you're adding/creating the views programmatically double check that the views 'translatesAutoresizingMaskIntoConstraintsis set toNO`. That always trips me up.
I made a super quick view and added some constraints to both a view inside the View Controllers view and an Image view to show one way to do it -- hopefully it helps at least a little
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.backdropView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
self.backdropView.backgroundColor = [UIColor colorWithRed:0 green:1 blue:0 alpha:0.5];
self.backdropView.translatesAutoresizingMaskIntoConstraints = NO; // Make sure this is set to NO if the view is being added programmatically
[self.view addSubview:self.backdropView]; // Always add the view into the hierarchy _before_ constraints are added (again, if creating & adding programmatically)
NSLayoutConstraint *backdropViewWidth = [NSLayoutConstraint constraintWithItem:self.backdropView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.backdropView.superview attribute:NSLayoutAttributeWidth multiplier:0.5 constant:0];
NSLayoutConstraint *backdropViewHeight = [NSLayoutConstraint constraintWithItem:self.backdropView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.backdropView.superview attribute:NSLayoutAttributeHeight multiplier:0.5 constant:0];
NSLayoutConstraint *backdropViewCenterX = [NSLayoutConstraint constraintWithItem:self.backdropView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.backdropView.superview attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
NSLayoutConstraint *backdropViewCenterY = [NSLayoutConstraint constraintWithItem:self.backdropView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.backdropView.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
[self.backdropView.superview addConstraints:#[backdropViewWidth, backdropViewHeight, backdropViewCenterY, backdropViewCenterX]];
self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
self.imageView.translatesAutoresizingMaskIntoConstraints = NO;
self.imageView.backgroundColor = [UIColor colorWithRed:1 green:0 blue:1 alpha:0.5];
[self.backdropView addSubview:self.imageView];
NSLayoutConstraint *imageViewTop = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.imageView.superview attribute:NSLayoutAttributeTop multiplier:1 constant:8];
NSLayoutConstraint *imageViewLeft = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.imageView.superview attribute:NSLayoutAttributeLeft multiplier:1 constant:8];
NSLayoutConstraint *imageViewRight = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.imageView.superview attribute:NSLayoutAttributeRight multiplier:1 constant:-8];
NSLayoutConstraint *imageViewBottom = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.imageView.superview attribute:NSLayoutAttributeBottom multiplier:1 constant:-8];
[self.imageView.superview addConstraints:#[imageViewTop, imageViewLeft, imageViewRight, imageViewBottom]];
[self.view layoutIfNeeded];
}
That produces and
Again, hopefully this helps.
EDIT: how to add them in storyboard
Note on photo 3, I select the view I want to constrain and then shift select the view I want to constraint it to. So I selected the inside UIView (because it width/height will be constrained to the parent view) then shift selected its parent view (the view it is nested inside of) to enable those options of Equal Width & Equal Height
Add constraints to UIImageView nested inside the UIView
Center UIView inside its parent view
Add width/height constraints equal to parent -- Note: I select the view I want to constrain and then shift select the view I want to constraint it to. So I selected the inside UIView (because it width/height will be constrained to the parent view) then shift selected its parent view (the view it is nested inside of) to enable those options of Equal Width & Equal Height
Change multiplier in constraint to be whatever you want, 0.5 in this case
Celebrate
i'm not sure but try this in your imageview.
[imgView clipToBounds:YES];
I hope it's work for you