Springs and struts resizing broken on iOS 8 UITableViewCell - ios

I'm trying to set up a simple UITableViewCell in Interface Builder without auto layout. I'm using the old springs and struts.
When I give a label a flexible width, it seems to lay out as if the UITableViewCell has a much larger width, even though the UITableViewCell tells me it has a width of 375 pixels in layoutSubviews:
- (void)layoutSubviews
{
[super layoutSubviews];
NSLog(#"Label width: %f", self.nameLabel.frame.size.width); // 695.0 for a label that stretches the whole width
NSLog(#"Superview (UITableViewCell) width: %f", self.nameLabel.superview.frame.size.width); // 375.0
}
On a simulated iPhone 5S (iOS 7 or 8), the superview is 320 but the UILabel spreads to 640.
On a simulated iPhone 6, the superview is 375 but the UILabel spreads to 695.
On a simulated iPhone 6 Plus, the superview is 414 but the UILabel speads to 734.
I don't have this problem with other views. For example, I'm able to add a UILabel to a UIViewController and have it stretch the width correctly. What is going on? And how do I fix this?
EDIT:
Interestingly, if I add the constraints programmatically during cellForRowAtIndexPath: then it seems to work as expected, so long as I use the older dequeueReusableCellWithIdentifier instead of dequeueReusableCellWithIdentifier:forIndexPath:. I want to keep all my constraints in Interface Builder though. Any ideas?

I played around a bit with this today. Looks like the frame of the label when it's instantiated relative to the frame of the content view is wrong. If I make the label the same size as the cell in the storyboard, then in awakeFromNib the contentView has a size of CGRectZero but the label has the size I set in the storyboard. Therefore, when you get to layoutSubviews and the contentView is resized to the right size (0,0,320,44), because of the flexible width mask, the label itself is resized along with the content view (width increases by 320 as well). That's why its appearing larger than intended.
The only way I could get around this (albeit, it feels like a gross hack and you should probably stick to auto-layout), was to set the label's frame relative to the content view in awakeFromNib.
- (void)awakeFromNib
{
[super awakeFromNib];
self.label.frame = self.bounds;
}

Related

UIScrollView doesn't work

These are my UIViews:
in my views I have 2 uitableview, 2 button.
I always check my UIView's sizes and these are the results:
randomPOC[2231:67151] MainView-1060.000000
2018-05-17 10:33:28.812877+0800 randomPOC[2231:67151] ScrollView-1060.000000
2018-05-17 10:33:28.813094+0800 randomPOC[2231:67151] ContentView-1060.000000
When my mainview , scroll and contentview have the same sizes, it doesn't scroll.
But when I divide the height into to 2 (height/2) of the mainview, it allows me to scroll. which makes me confused how and why.
when I divided the mainview height into to 2 it allows me to scroll but it doesn't covers down to the last of the tableview.
I need to resize the mainview because I need to cover the two(2) uitableview that has sometimes more than 1000height.
_mainView.frame=CGRectMake(_mainView.frame.origin.x, _mainView.frame.origin.y, _mainView.frame.size.width, uitableview2.height );
This answer has nothing to do with why your UIScrollView doesnt work.
UIScrollView will only scroll if its content size is greater than its frame size.
You should first decide the size of your UIScrollView frame, Than for a Veritical UIScrollView you should assign the content size as follow:
Lets say you have 5 UIView's which have height of 5 dp each, than you should set the UIScrollView height like so:
scrollview.setContentSize(width, 5*5).
Than if the UIScrollView frame height is greater than 25, the UIScrollView will not scroll.
Else the UIScrollView will scroll.
hope it helps!
Found the answer by using this resizing the mainview like this instead:
_mainView.frame=CGRectMake(_mainView.frame.origin.x, _mainView.frame.origin.y, _mainView.frame.size.width, [[UIScreen mainScreen]bounds].size.height );

UIView for Table View Header Width Wrong

I have a UIView as my tableview header but the width is slightly smaller than the simulator for some reason. I haven't been able to fix this. The tableview is inside of a view controller and the UIView has been allocated like this:
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.frame.size.width, 40.0)];
The width is showing 375 instead of 400 as it is supposed to be so it is slightly smaller in the iPhone 6 simulator and on my iPhone 6.
I know the width of the iPhone 6 itself is 375, but if you see the view's width in the size inspector it says 400 as you can see in the image below. Also you can see how the UIView is slightly smaller than the UITableView width. This could be due to some spacing issue also, I am not sure. The constraints added to the uitableview were 0 spacing on the top and bottom and -20 on the left and right.
You should set your frame in:
viewDidLayoutSubviews
Because in it frame is correct.
I had a feeling it was the -20 spacing that I had on my tableview. I wasn't sure how to make it 0, but walk_alone suggested unchecking constrain to margins and this allowed me to set the spacing to 0 for both of the side constraints. This allowed for the UIView to take up the full width.

How to access correct width value from IB with Autolayout

I have some strange Issues.
I have a UIViewController and only 1 UIView (I call it containerView) inside. The UIView should have the same Width as the UIViewController.
So I set the Leading and the Trailing Constraints between the UIView and the UIViewController to 0. During runtime everything works fine, BUT, how can I access the actual width during runtime? I tried it with:
self.containerView.frame.size.width
but of course frames doesn't work with autolayout and I only got a width of 600.0f, which is the standard width from the Interface Builder!
I also tried to set a fixed Constraint Width but this also makes no sense because the iPhone has a different Screen Width as the iPad for example.
Any Ideas how i can access the Width of my UIVIew during runtime.
PS: As you can see i use Interface Builder, Size Classes and Autolayout!
try to get the width in viewDidLayoutSubviews
-(void)viewDidLayoutSubviews
{
NSLog(#"%f", self.containerView.frame.size.width);
}
and since your UIView have 0 space to all screen edges the width of the UIView will be the same as the screen size so you can get it like this:
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;

Autoresize UIPopoverController using autolayout

I'm trying to use autolayout to automatically resize my popover to fit it's contents. I have fixed popover width but to compute height i rely on systemLayoutSizeFittingSize: passing my predefined width and zero height e.g. CGSizeMake(190, 0).
ContentController* controller = [ContentController new];
CGSize preferredSize = [controller.view systemLayoutSizeFittingSize:CGSizeMake(190, 0)];
controller.preferredContentSize = preferredSize;
UIPopoverController* popover = [[UIPopoverController alloc] initWithContentViewController:controller];
//popover presentation.
So far, so well, my current ContentController view hierarchy is something like (setup in the Interface Builder):
UILabel - multiline header (dynamically resized)
|
UIImage with fixed width / height (static size)
|
UILabel - multiline body (dynamically resized)
Thus, i just plug in my header / body text, call systemLayoutSizeFittingSize and it returns valid size that fits all the content of the view.
The problem arises when i try to put my body label inside UIScrollView. (Both in the IB and in code).
From now on, systemLayoutSizeFittingSize will not take body label height into account and will return height for header + image.
I've setup all the constraints in the IB to support Pure Autolayout approach.
I've checked scrollview's content size - it is indeed equals to body label's intrinsic size, but scroll view's frame is squashed into 0.
I've checked and tried to reset label's maxPreferredLayoutWidth to the width of the content view, but it doesn't seems to affect anything.
I've set translatesAutoresizingMaskIntoConstraints on every view to NO, but it has no effect.
I've set hugging / compression resistance priorities of both label and it's scrollview to 1000, but no luck. Setting them on the container view doesn't work either.
Here are screenshots of my IB view setup:
My guess that is is somehow related to popover hosting views and their autolayout constraints, but i'm not sure.
I'm updating my labels via simple
_textContainerHeaderLabel.text = headerText;
_textContainerBodyTextLabel.text = bodyText;
[self.view setNeedsUpdateConstraints];
[self.view layoutSubviews];
So, the main question - how do i compute view's optimal fitting size via autolayout when it has UIScrollViews in it?
Finally found a solution for this case. Don't know how correct it is, but i did the following - I've added height inequality constraint (>=0) from label to it's scrollview.
The trick is to make this constraint's priority lower than label's compression resistance (vertical, in my case). This seems to to solve this problem.

UIScrollView content size clipping subviews when it shouldn't

I have a UIScrollView that contains several dynamically resizing subviews. I can resize and layout the subviews just fine, but when I set the content size of the scroll view itself, the bottom subviews are clipped. Is there some reason why a scroll view's content size height should be larger than the sum of the heights of the views it contains?
Here's my situation in more detail:
I have a superview containing a UIScrollView containing several subviews. In the superview's layoutSubviews method, I calculated the needed size of each subview, then set the frames so the subviews are tiled vertically down the screen with a bit of space between them. When done, I set the height of the UIScrollView's content size to be the end of the last subview (origin.y + size.height). In theory, this means the bottom of the scroll view's content area should exactly line up with the bottom of the last subview.
But it doesn't. Instead, a nice chunk of the last subview is clipped. It's still there - if I scroll down I can see the remaining portion during the "bounce". The problem is even worse in landscape mode - a much larger portion of the bottom subview simply isn't visible.
The subviews are all being arranged and positioned properly. The problem is that the UIScrollView's contentSize seems to need to be significantly larger than the sum of the heights of the subviews (plus the space between them). This doesn't make any sense to me. Furthermore, the amount the size is "off" varies - I reuse this view several times with different subviews, and they're all off by a different amount. Therefore, simply adding a constant to the content view height won't help.
What is causing the content size (or my height calculations) to not function correctly?
Code:
- (void)layoutSubviews
{
[super layoutSubviews];
CGFloat width = self.bounds.size.width - [self subviewLeftMargin] - [self subviewRightMargin]; // All subviews have same width as parent view
CGFloat x = [self subviewLeftMargin]; // All subviews should start at the far left of the view
CGFloat y = [self spaceBetweenSubviews]; // Running tally of the y coordinate for the next view
/* Adjust the subviews */
for(UIView *view in self.theVariousSubviews) {
/* Resize the view with the desired width, then let it size its height as needed */
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, width, view.frame.size.height);
CGSize newSize = [view sizeThatFits:view.frame.size];
/* Set the origin */
//The subviews are positioned correctly, so this doesn't seem to be a problem
view.frame = CGRectMake(x, y, newSize.width, newSize.height);
/* Have the view refresh its own layout */
[view setNeedsLayout];
/* Update the y value for the next subview */
y += newSize.height + [self spaceBetweenSubviews];
}
/* Resize the scroll view to ensure it fits all of the content */
CGFloat scrollViewHeight = y;
self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width, scrollViewHeight);
//Content size is set to the same total height of all subviews and spacing, yet it is too small. Why?
}
hi it seems to me that your calculation and resizing timing is wrong.
Without the missing code for the layout change I could not fully understand the problem.
What strikes me is that you are assigning view.frame twice and between the new calculation you intercept the process with sublayouting which might change some of the values your calculation is depending on.
I could only advice you to separate the calculation from layouting and not invoke methods while you are calculating. To bring light into it you should either drop a sample app with the missing calculation or for yourself add some NSLog statement showing you the frame origin size of any subview and the contentOffset for the scrollview.
On my experiences the scrollview is working properly in general so I would expect a bug within your code.

Resources