After I updated to Xcode 9, UITableView in iOS 10 device is behaving very strangely. The tableView cell sizes are not maintained. It it resizing by itself and not following the constraints and cell sizes I had explicitly coded. The gap between the tableView cells is black all of a sudden. However, these layout issues are not reciprocated in iOS 11 handset.
In a nutshell, the layout is completely screwed in iOS 10 devices. Is anyone else having backward compatibility after updating to Xcode 9? If so how did you resolve it.
To change the frame width of the custom table View cell cell I am using the frame property. The code I am using is
override var frame: CGRect {
//Decrease frame width of the tableViewCell
get {
return super.frame
}
set (newFrame) {
var frame = newFrame
frame.origin.x += 8
frame.size.width = frame.size.width-16
super.frame = frame
}
}
Below is how the tableViewCell is presented in iOS 11 which is correct
this is how the tableViewCell is presented in iOS 10 which is incorrect
[
As you can see the gap from right margin to the tableView Cell is more.
Throw away your existing code. Don't touch the cell's frame in any way.
To make cells that look narrower than the table, give the cell a clear background and put an opaque view inside the content view that is inset from the cell's bounds (or you could use the cell's background view for this). Use autolayout to configure this, so that it works regardless of screen size.
Related
Before Xcode 9, I had a working tableview where in cellForRowAtIndexPath: I would check if viewWithTag(1) was nil, as a flag for whether or not this cell needed some initial setup. If so, I'd create some views and add them as subviews to the cell's contentView. I would also position these subviews using the contentView's bounds.
After Xcode 9, the positioning of these subviews are all messed up, and I found that when cellForRowAtIndexPath: is called, the cell's bounds and the cell's contentView's bounds are not what they should be. Their height is 44 points, which I guess is the default row height. But it should be 100, because in my viewDidLoad I call:
self.tableView.rowHeight = 100
I don't know whether this is just a problem I'm experiencing or if its a bug / change in Xcode 9.
First of all this is not a question about how to automatically size the cells inside the tableview, moreover how to automatically resize the entire tableview.
So I have a scrollview which has a tableview and 2 other views as its subviews. The tableview's cells already automatically resize itself, again this question is not about the individual cells. However, the tableview does not resize at all.
What I have done:
1) Set up the tableview to have a top, bottom, leading and trailing constraint
2) Set the cells up to have auto layout enabled
3) * I do not know the cell size at build time
4) I have disabled scrolling mode on tableview
So long story short, how can I go along to get the tableview to resize itself?
Edit
The cells contain a label which can have various lines of text, so therefore the cells, which use auto layout, should then determine the height of the table view.
The following images show how the view is set up:
As you can see the tableview is only a small part of the view and since the scrollview from the tableview is deactivated there should, and aren't, any scrolling problems.
EDIT 2
This is actually how it should end however, i am calculating this on my own and everytime I want to make a small change to the cells the whole code, which calculates the height of the cell, needs to be rewritten and it is quite difficult for me to get the height just right.
Edit 3
Until now I had a height constraint on the tableview which I calculated manually, however removing this constraint and trying to let auto layout handle the tableview height size creates the following error:
Scroll View
Need constraint for: Y position or height
I can conclude therefore that the tableview does not know how to automatically calculate the height based on its cells with autolayout.
You don't need to create a height constraint or set frame whatsoever. Create a subclass of UITableView and recalculate its intrinsicContentSize every time its contentSize changes aka new data added or removed. Here is all you needed:
class SelfSizingTableView: UITableView {
override var contentSize: CGSize {
didSet {
invalidateIntrinsicContentSize()
setNeedsLayout()
}
}
override var intrinsicContentSize: CGSize {
let height = min(.infinity, contentSize.height)
return CGSize(width: contentSize.width, height: height)
}
}
You can change your UITableView's frame by using tableview.frame = CGRect(x: <some_x>, y: <some_y>, width: <some_width>, height: <some_height>)
If your UITableViewCells use auto layout then they should resize when the UITableView's frame changes.
As I'm using UITableView and the custom cell inside tableview setting its width to 320 in IPhone 5,IPhone 5s and IPhone 4 and less but in IPhone 6 and 6P it is not resizing tableview cell width to 414 on initial load even i'm calling tableview reloadData in viewDidLoad too.I know tableview use default value of its size on inital load but I want its initial width to be 414 on Iphone 6 & Ipone 6P...
As I'm using custom cell too..and its width is also 320 in Iphone 6 & Ipone 6P I know it is becoz of tableview...
I had called all layout methods but no luck...Can Someone resolve this of my mine and put some light on this topic...
I had done..
cell.bounds = [UIScreen mainscreen].bounds;
in cellforrowatindexpath but i think this is not precise solution but it is working fine...
Autolayout is always easy and good but if you want programmatically
You should get the screen size (width) at run time and then update the table view frame
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated)
tableView.frame = CGRectMake(tableView.frame.origin.x, tableView.frame.origin.y, set_new_width_here, tableView.contentSize.height)
//or
var tableFrame: CGRect = tableView.frame
tableFrame.size.width = set_new_wdith_here
tableListView.frame = tableFrame
}
PS: if you absolute beginner with auto-layout I would suggest please try to reset auto-layout constraints it works almost every time i use.
Please use AutoLayout on tableView and give Leading,Trailing,Top and Bottom Constraints to tableView with its SuperView,So tableView's frame will be according to its SuperView in all devices.
I want to get my UITableViewController to scroll only when there is not enough room on the screen for all of its cells. I am using static cells that are designed to be shown in an iPhone 5, 6, and 6 plus size screen. However, when shown in the 4s screen, the bottom cells get cut off.
Ideally I would like to use AutoLayout to anchor the bottom of the tableview to the bottom of its superview as I have with other tableviews in my application, but Xcode doesn't allow me to add constraints to the UITableView in a UITableViewController. The reason I have to use the UITableViewController is because I am using a pod for a slide menu (https://github.com/SocialObjects-Software/AMSlideMenu) that subclasses UITableViewController.
I have tried to change the size of the UITableView's frame based on the screen size because I assumed a scroller would automatically be added if the cells took up more room than the containing frame. I used the following code to do so:
CGRect frame = self.tableView.frame;
[self.tableView setFrame:CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, [[UIScreen mainScreen] bounds].size.height - HEADER_HEIGHT)];
However, it had no effect on the way the table was displayed.
Does anyone know how I might be able to set the bottom of the UITableView dynamically and add a scroller to the cells when the screen is too small? I would also welcome any suggestions that might help avoid having to do this at all, as I would prefer not having to do anything too hacky.
You can set the alwaysBounceVertical property to false so the tableView will only scroll when its contentSize is larger than the table view's frame which you can constrain to your view however you like.
tableView.alwaysBounceVertical = NO;
UITableViewController height is determined by automatically calculating number of UITableViewCell you have presented. You can customize the cell height so that height of UITableViewController will automatically changed as you wished.
My UICollectionView cells don't get displayed on iOS6, because my delegate method cellForItemAtIndexPath doesn't get called. I suspect because of this warning:
the behavior of the UICollectionViewFlowLayout is not defined because:
the item height must be less that the height of the `UICollectionView`
minus the section inset's top and bottom values.
I don't get the warning on iOS7, and all the cells display correctly there too.
I've set my collectionView frame to height 270 in the .xib and there are no insets defined.
I've set my cell height to 270 in the .xib.
I can print out my collectionView frame at runtime and it's 271.
Also, my collectionview is actually inside a custom tableview cell.
Any ideas?
Thanks!
Try to set self.automaticallyAdjustsScrollViewInsets = NO
This was introduced in ios7 so you might want to wrap that with an ios version check, if you are supporting ios6 and below.
This fixed my problem! In my .xib, setting my Collection View Size Cell Size to a smaller value.
My setup is that I have this collectionview inside a custom tableview cell and
I do return the height of my tableview cell programatically (depending on the content). So it could be that my warnings had to do with my collectionview not fitting inside the tableview cell. So setting the initial collectionview to a smaller value fixed it.
I was on the wrong path thinking that the problem was with my collectionview and its colletionview cell.
Maybe?
self.automaticallyAdjustsScrollViewInsets = NO
actually did the trick. it also resolved my issue in swift, where the cells of a horizontal flow layout had a frame top of -32 (???) and did not fit into the collection view properly.
I found that I had to manually set self.collectionView.collectionViewLayout.itemSize in viewWillLayoutSubviews.
- (void)viewWillLayoutSubviews {
self.collectionView.collectionViewLayout.itemSize = CGRectMake(...);
}
Another possibility to generate the same trick would be to implement the method
collectionView:layout:sizeForItemAtIndexPath:
I have the same issue, in my case the size of collectionCell in storyboard is 96x96 and also under -(CGSize)collectionView:layout:sizeForItemAtIndexPath:
the solution was removing this delegate:
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
UIEdgeInsets insets = {.left = 10, .right = 10, .top = 5, .bottom = 5};
return insets;
}
And by the way this is under ios7, it's late but hope this will help some.. Cheers..
Set:
self.itemSize = CGSizeMake(1, 1);