What is the correct way to use UIScrollView? - ios

I tried to setup a simple view which displays a text-only article with a headline. Here are the steps that I've done:
Create View Controller with its .xib file,
Create UIScrollView and places a UIView directly as the content wrapper,
Set the constraints [scrollview]-0-[superview] in top, bottom, leading, and trailing.
Set the constraints [content wrapper]-0-[scroll view] in top, bottom, leading, and trailing.
Set Width and Height to content wrapper as placeholder.
Add Label and UITextView as content wrapper's subviews.
Add constraints to the subviews.
Following this tutorial, I programmatically set content wrapper's leading = scrollview's superview left,
... And content wrapper's trailing = scrollview's superview right.
When I ran the code, it shows everything in place perfectly; The UIScrollView scrolls, margins are properly set, etc.
However, Xcode throws an exception:
2015-02-05 18:06:58.230 ScrollViewApp[5353:180401] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7ff9fa49a3f0 H:[UIView:0x7ff9fa571560(600)]>",
"<NSLayoutConstraint:0x7ff9fa49b1a0 H:|-(0)-[UIView:0x7ff9fa571560] (Names: '|':UIScrollView:0x7ff9fa49a910 )>",
"<NSLayoutConstraint:0x7ff9fa49ce00 H:|-(0)-[UIScrollView:0x7ff9fa49a910] (Names: '|':UIView:0x7ff9fa49a840 )>",
"<NSLayoutConstraint:0x7ff9fa61c050 UIView:0x7ff9fa571560.right == UIView:0x7ff9fa49a840.trailing>",
"<NSLayoutConstraint:0x7ff9fa580970 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7ff9fa49a840(375)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7ff9fa49a3f0 H:[UIView:0x7ff9fa571560(600)]>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
After further googling, I found out that I can dismiss the warning by setting content wrapper's width (see step 5 above) priority to low; however it breaks the layout in interface builder. Take a look:
Compared to when it's set to High priority:
I know that in the end it makes no difference because it's both working as expected.. But I'm kind of curious as to why these things happen..
I'm trying to understand how UIScrollView works, but maybe I'm misunderstanding something; so, what is the proper way for setting up UIScrollView to work as expected?

Try to add a center horizontally constraint from your content wrapper to your scroll view.
To be honest, I really don't know why that works, i figured this one out by trial an error. If you want your view to be compatible different screen sizes, remove the width constraint of the content wrapper.
Hope it helped.

you can use scrollview like this. Add scrollview in design. Give it's left, top, right, bottom constraints in design. Add your subviews in scrollview. Add proper constraints for them. There is no need to add constraints in code. In viewDidLayoutSubviews set your scrollview's content size.
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
CGRect boundsOfSelf = self.view.bounds;
scrollView.frame = boundsOfSelf;
[scrollView setContentSize: boundsOfSelf.size];
}

Related

Unable to simultaneously satisfy constraints When trying to load xib file

I am trying to implement the UITableView using xib file
But when I run the app I am getting the following error & the xib is properly in small screen like iPhone4s
it works fine in larger display size.
Screenshot of xib
Any help will be appreciated
Error
2016-12-14 17:12:41.826 FoodStrock[5776:1761262] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x7fcc2a6dfac0 V:[UIImageView:0x7fcc2a6e1010(63)]>",
"<NSLayoutConstraint:0x7fcc2a617530 V:[UIImageView:0x7fcc2a6e1010]-(8)-| (Names: '|':UITableViewCellContentView:0x7fcc2a6e1270 )>",
"<NSLayoutConstraint:0x7fcc2a6cc3b0 V:|-(9)-[UIImageView:0x7fcc2a6e1010] (Names: '|':UITableViewCellContentView:0x7fcc2a6e1270 )>",
"<NSLayoutConstraint:0x7fcc2a4955a0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fcc2a6e1270(59.6667)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7fcc2a6dfac0 V:[UIImageView:0x7fcc2a6e1010(63)]>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2016-12-14 17:12:41.827 FoodStrock[5776:1761262] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x7fcc2a6a69d0 V:[UILabel:0x7fcc2a6e1670'Address'(63)]>",
"<NSLayoutConstraint:0x7fcc2a693820 UILabel:0x7fcc2a6e1670'Address'.bottom == UITableViewCellContentView:0x7fcc2a6e1270.bottomMargin>",
"<NSLayoutConstraint:0x7fcc2a6e0c00 UILabel:0x7fcc2a6e1670'Address'.top == UITableViewCellContentView:0x7fcc2a6e1270.topMargin + 1>",
"<NSLayoutConstraint:0x7fcc2a4955a0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fcc2a6e1270(59.6667)]>"
)
Put your UIImageView , UILabel, UIButton in single UIView(says mainView). Now mainView constraints will be leading, trailing, top bottom from the xib view(superView). Now constraints of UIImageView , UILabel, UIButton is according to your requirement w.r.t. mainView.
NOTE: Give constraints to the UIComponents as minimal as possible but keep mind about it full fills your requirement. Like here, give constraints like this:
UIImage : top, bottom , Leading wrt mainView and constant width or you can give horizontally center to container, leading, height, width.
UIButton : top, bottom, trailing wrt mainView and constant width or you can give horizontally center to container, leading, height, width.
UILabel : leading trailing and horizontally centre to container is enough but you can give height also.
UILabel can automatically take height and width according to the text font size you just need to specify x and y coordinates.

iOS autolayout: set constraints in viewDidLayoutSubviews?

I have a view controller with xib. xib contains all the subviews without constraints and I need to add these constraints manually. Everything is correct when I write my code in viewDidLoad. But I need to get a size parameter which is available in viewDidLayoutSubviews only. When I try to call my code in viewDidLayoutSubviews then I get the following error:
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x79edebb0 V:|-(50)-[UILabel:0x79f11bf0'You haven't imported any ...'] (Names: '|':UIView:0x79f11940 )>",
"<NSLayoutConstraint:0x79e4b190 V:|-(49)-[UILabel:0x79f11bf0'You haven't imported any ...'] (Names: '|':UIView:0x79f11940 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x79edebb0 V:|-(50)-[UILabel:0x79f11bf0'You haven't imported any ...'] (Names: '|':UIView:0x79f11940 )>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
The constraints are simple: all the views are placed in one column, fixed width, fixed height, distance between topmost view and superview's top border, distances between neighbour views and finally all the views are snapped to the superview's horizontal center.
UPDATED
I found the reason of the problem but I don't know why it doesn't work.
The problem is the topmost constraint value was based on views' bounds. The height value inside this bounds structure "jumps" by 1 (because viewDidLayoutSubviews is called multiple times). But why does it cause problems with constraints?
it says that 1 of the UILabel have Constraint which breaks layout.
2 options
clear Constraint of all label and set Constraint of each label by try n error
set id to all constraint of uilabel and then u will see id of constraint in
warning or error output.
basically it is due to u added an unwanted constraint.

Using auto layout and systemLayoutSizeFittingSize

I have a really simple view that I cannot for the life of me figure out the problem. I have successfully used auto layout and systemLayoutSizeFittingSize for fairly complex custom UITableViewCells. This is my first time using it for a UIView (to be used in a UITableView.tableHeaderView) and I cannot get it to work.
I have a simple label in the view that I want to cover the entire view. I have added the Trailing, Leading, Top, and Bottom constraints to the label against the parent's corresponding edges. When I do this, systemLayoutSizeFittingSize computes the correct height, but I get the following error:
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7fbb71d9a310 V:|-(5)-[UILabel:0x7fbb71df5120'Test Label'] (Names: '|':mailapp.MailTableHeaderView:0x7fbb71d2c490 )>",
"<NSLayoutConstraint:0x7fbb71d2ebf0 UILabel:0x7fbb71df5120'Test Label'.bottom == app.HeaderView:0x7fbb71d2c490.bottom - 5>",
"<NSLayoutConstraint:0x7fbb71de31d0 V:[app.HeaderView:0x7fbb71d2c490(0)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7fbb71d2ebf0 UILabel:0x7fbb71df5120'Test Label'.bottom == app.HeaderView:0x7fbb71d2c490.bottom - 5>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
Now, if I remove the "bottom" constraint on the label, auto layout works correctly but now systemLayoutSizeFittingSize returns 0.
What is the right way to make the constraints satisfy the auto layout engine but also to have systemLayoutSizeFittingSize compute the correct size?
As I mentioned, the most baffling thing is that I have used this successfully for complex auto layouts, but I noticed all those were UITableViewCells. I'm not sure if there is a difference.
I figured out the problem, but I don't understand why. For the UITableViewHeader, I cannot do the typical auto layout thing for the view. That is, I have to set translatesAutoresizingMaskIntoConstraints to be true. Effectively, I cannot use auto layout for the header view, and I have to set the frame manually.
Within the header view, I can use auto layout for the sub views successfully.
So my algorithm goes like this for constructing the tableHeaderView:
Create the header view with any arbitrary frame
Compute the constraints (of the header view's subviews)
Set the frame.width of the header view to match the parent tableView.frame.width
Layout the header view
Use systemLayoutSizeFittingSize to compute the height
Update the header view's frame.height
This works for me. I was not able to get it to work if I created the header view with translatesAutoresizingMaskIntoConstraints set to false.
As per the Apple Visual Format Language the following appears to be setting a '0' height constraint on your HeaderView.
E.g.
"<NSLayoutConstraint:0x7fbb71de31d0 V:[app.HeaderView:0x7fbb71d2c490(0)]>"
I would start by investigating this, as having a height of 0 will likely mess up your other label constraints for top and bottom spacing.

AutoLayout issue in dynamic UITableViewCell's subviews

While I seem to have taken the gist of setting the view constraints on UIViews of storyboards, I just can't seem to figure out why constraints are not properly working in a dynamic cell prototype ContentView's subviews.
The cell is pretty simple: A UIImageView background that fills the entire cell, in front of it another UIImage and a label as following:
The background UIImageView has the following 4 constraints:
0 fixed to: trail, bottom, top and leading space to superview
The profile picture image has a fixed width and height and a constant 13pts space to leading superview and has a vertical center in container
The Label has an 8pt leading space to the profile pic and trailing space to superview, and has a vertical center in container.
This is what I am getting:
Did I miss something? I researched the issue but no answer solved the issue. However, I tried adding the following lines in the cellForRowAtIndexPath after loading the cell:
cell.setNeedsUpdateConstraints()
cell.updateConstraintsIfNeeded()
which gave the following errors at runtime:
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"NSLayoutConstraint:0x7fe5434852c0 H:[UIImageView:0x7fe543484450(75)]",
"NSLayoutConstraint:0x7fe5436c5cd0 H:|-(12)-[UIImageView:0x7fe543484450] (Names: '|':UITableViewCellContentView:0x7fe5434820f0 )",
"NSLayoutConstraint:0x7fe5436c34e0 H:[UILabel:0x7fe543487430'Joseph']-(8)-| (Names: '|':UITableViewCellContentView:0x7fe5434820f0 )",
"NSLayoutConstraint:0x7fe5436bcca0 H:[UIImageView:0x7fe543484450]-(8)-[UILabel:0x7fe543487430'Joseph']",
"NSLayoutConstraint:0x7fe5436cb110 'UIView-Encapsulated-Layout-Width' H:[UITableViewCellContentView:0x7fe5434820f0(0)]"
)
Will attempt to recover by breaking constraint
NSLayoutConstraint:0x7fe5434852c0 H:[UIImageView:0x7fe543484450(75)]
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in UIKit/UIView.h may also be helpful.
Any clues?
Well, problem is priorities.
You have background image, which has some size according to image you put into it and than there is a profile picture with fixed height and constant space 13pts top and bottom.
Table may have separator and that one is adding extra space.
So advice: lower for example bottom 13pts constrains from 1000 to 750. That should remove warning.

Autolayout contraint error

So this autolayout error. Which I know why it is there but I am not sure how can I fix it. As with error its clear that its not able to resolve the constraints.
In portrait mode all 47 episode are listed and can be scrolled to. But in landscape mode it cant, which is clear as height of table is not changing thats way its is still down there but can't scroll to it.
So this is how I have setup.
Where as view controller has two view which works as placeholder upper is of for iAds and lower is holding table view. Idea was behind this. if ad is not loaded I will set height of View to zero which holds iADBanner. So that Table view takes up all space. (Got this idea from Ray Wenderlich's app level me up.) I was struggling with auto layout initially but I made it right so that view are taking up all width when sim goes to portrait mode. but somehow I am not able to fix the height of view which holds tableView.
Below are the screenshot of constraints.
I tried to be as descriptive as I can. but I am looking for more than just answer. I want to get to know this completely so that I will most likely won't have problem in future. I have finished raywenderlich tutorial already. So Any other pointer would be very much appreciate along with the answer.
2014-07-30 21:40:37.326 Test[85608:60b] Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) (
"<NSLayoutConstraint:0xa5afbc0 UIView:0xa69b7d0.width == 0.682303*UIView:0xa69b830.height>",
"<NSLayoutConstraint:0xa5afc80 V:|-(50)-[UIView:0xa69b830] (Names: '|':UIView:0xa69b7d0 )>",
"<NSLayoutConstraint:0xa5afdc0 V:[UIView:0xa69b830]-(0)-[_UILayoutGuide:0xa5a8410]>",
"<_UILayoutSupportConstraint:0xa5a7d20 V:[_UILayoutGuide:0xa5a8410(0)]>",
"<_UILayoutSupportConstraint:0xa5af490 _UILayoutGuide:0xa5a8410.bottom == UIView:0xa69b7d0.bottom>",
"<NSAutoresizingMaskLayoutConstraint:0xa792d10 h=--& v=--& H:[UIView:0xa69b7d0(480)]>",
"<NSAutoresizingMaskLayoutConstraint:0xa792dd0 h=--& v=--& V:[UIView:0xa69b7d0(271)]>" )
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xa5afdc0 V:[UIView:0xa69b830]-(0)-[_UILayoutGuide:0xa5a8410]>
Break on objc_exception_throw to catch this in the debugger. The
methods in the UIConstraintBasedLayoutDebugging category on UIView
listed in <UIKit/UIView.h> may also be helpful.
The list of constraints in the error log is the key to understanding this type of problem. What you want to do is look at it carefully to correlate which lines refer to which constraints in your code/ui builder, and which hexadecimal address refers to which view.
V:[UIView:0xa69b830]-(0)-[_UILayoutGuide:0xa5a8410] is a constraint setting the bottom of a UIView to a layout guide, so most likely that's the last constraint in your screenshot "Vertical Space - Bottom layout guide - TableVi..." (presumably that's TableViewHolder truncated). That means UIView:0xa69b830 is your TableViewHolder.
V:|-(50)-[UIView:0xa69b830] (Names: '|':UIView:0xa69b7d0 ) is the constraint tying the top of TableViewHolder 50px from its superview, which must be UIView:0xa69b7d0.
UIView:0xa69b7d0.width == 0.682303*UIView:0xa69b830.height looks like an aspect ratio constraint between the superview width and the TableViewHolder height.
h=--& v=--& H:[UIView:0xa69b7d0(480)] and h=--& v=--& V:[UIView:0xa69b7d0(271)] are constraints on the superview that's derived from its autoresizingMask, where the width=480px, height=271px, and their top/left/width/height are fixed (based on h=--& v=--&). This is sort of the standard setup for the root view of a view controller — it's dimensions are managed manually by the view controller to fill the screen.
So once you have all that, you can see what the problem is: the superview has fixed dimensions 480x271. Meanwhile, TableViewHolder's height is being dictated by multiple conflicting constraints:
#1 and #2 are trying to stretch it vertically to fill its superview with a 50px margin at the top, so height = 271-50 = 221px.
#3 is trying to set the height as a ratio of the superview's width: height = 480/0.6823 = 703.5px
221 != 730.5!
Something's gotta give, and the OS just happened to pick #1, so the bottom of TableViewHolder extends past the bottom of the layout guide, making it stick out past the edge of the screen and inaccessible.
Your fix will likely involve getting rid of that aspect ratio constraint, but there might be other issues that appear once you fix that. Good luck!

Resources