UICollectionView working on iOS7 but not on iOS6 - ios

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);

Related

iOS 8 : how to set height programmatically for a UITableview in a freeform ViewController

Rookie in iOS.
I have a Freeform ViewController, which has an UIImageView and
UITableView in it.
The Problem i am facing here is when i try to scroll the tableview
some of the items stay hidden because of the height it has taken in the freeform
viewcontroller.
I tried the following code to set the UItableview's height programmatically
according to the size of the screen.
let screenSize: CGRect = UIScreen.mainScreen().bounds
tableview.frame = CGRectMake(0,imageview.frame.height, 280, (screenSize.height -imageview.frame.height))
The above code failed to resize the tableview.
Is there any other way that i can set the UITableview size at Runtime or
in the storyboard.
Solution
I resolved the issue after laid out my both views using custom height and width after specifying translatesAutoresizingMaskIntoConstraints = true for both the views. I did as per my design and app requirement.
if you are using auto layout or constraints, you have to
tableview.translatesAutoresizingMaskIntoConstraints = true
before applying the new frame, the new frame is not updating because it's getting over-riden by auto layout and constraints.
EDIT :
1- if you have [adjust scroll view insets] enabled in your view controller in story boards disable it, and test and see.
2- do you create the imageView programatically? or from interface builder, and do you have constraints on it?
3- did you know that the status bar has a height and you have to compensate for it too?
4- do you use a navigation bar?
There is a delegate function for the UITableViewCell height.
Here you specify the indexPath of that particular cell and return your height for it
(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.section == yourSection && indexPath.row == yourRow) {
return 140.0; //return height for required row
}
// "Else"
return someDefaultHeight;
}
Don't set Tableview height programmatically.
Just do one thing
Take Top, Bottom, Leading, Trailing constraints and set constant value to 0
Add user image view into tableview header.

seprator is not visible in uitable view for dynamic height?

I am designing an app in which i have used a table view.This table view uses a custom cell.I have given proportinal height to the table view.T
tableview height constraints:
equal height to mainview
multiplier:189:568
Cell properties
cell height:77
Image constraints:
Label constraints
TextViewContsraints
bottom right label constraints
Code to make the row height dynamic
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:
(NSIndexPath *)indexPath
{
float percentage = (77.0 / 568.0);
float height = self.view.frame.size.height * percentage;
return (height>77.0)?height:77.0;
}
Issue screen
Is the UITableViewCell in IB associated with a UITableViewCell subclass that overrides drawRect:? If so, make sure you are calling the super implementation, as that's what draws the line at the bottom. If you are overriding layoutSubviews make sure no views are obscuring the bottom of the cell.
In my case, i forgot to call [super layoutSubviews] after overriding the layoutSubviews method. Took me hoursto find the problem.
Hope this will help you.
Increase custom cell size to 80-88 may be it solve your problem

iOS8 Beta 3 UITableViewCell layoutSubviews infinite loop

There were auto-resizable table view cells introduced in iOS8 (WWDC Session 226 What's new in table and collection views).
In my project I'm trying to implement old fixed rows height behavior. Also, the most important thing for me is to inset default cell.contentView frame with margins on the left and right side.
So, I change the cell.contentView.frame property and immediately after that the -[cell setNeedsLayout] method is being called and and it leads to cell get stuck in an infinite layoutSubviews loop.
Steps to reproduce:
Create new single view project and replace default view controller with the table view controller
Disable table view automatic height calculation
-(void)viewDidLoad {
[super viewDidLoad];
self.tableView.estimatedRowHeight = 0;
self.tableView.rowHeight = 44;
}
3. Drop a custom cell in the table view in storyboard,
Add any subview to the custom cell:,
Subclass the cell and change contentView.frame in layoutSubviews,
Build and run.
Result:
Simulator ends up in a black screen stuck in a infinite layout subviews loop.
Expected Result:
Simulator displaying a table view with a cell's contentView having a custom frame.
Comment:
While debugging a little bit, I found that the infinite loop can be avoided if the cell does not have any custom subviews dropped on it. So it seems the bug will appear after the following conditions are met:
self.tableView.estimatedRowHeight = 0; self.tableView.rowHeight = 44;
cell.contentView.frame = CGRectMake(...)
cell have custom subviews dropped on it in xib or storyboard
Apple does not have the issue in the "Known issues" list for iOS8, so I'm wondering is it actually a bug in iOS8 or does anybody know how to resolve the issue?
This is not a bug: setNeedsLayout will be called any time you change view's frame.
My guess is that changing cell.contentView.frame also changes cell.bounds in iOS 8, triggering relayout. This behavior may be different between iOS versions; anyway, those are standard views, so we shouldn't change them in unsupported ways.
Rather than operating on cell.contentView, how about adding a custom view with insets to it? Or simply creating a height constraint?
In ViewDidLoad please use the below line and there is no need to give the row height
-(void)viewDidLoad {
[super viewDidLoad];
self.tableView.estimatedRowHeight = 44.0f;
self.tableView.rowHeight = UITableViewAutomaticDimension;
}

UICollectionView Layout Issue

I am using UICollectionView using the flow layout.
I have made a custom UICollectionViewCell for the same.
But on running the project the console keeps on throwing this error-
The behavior of the UICollectionViewFlowLayout is not defined because:
the item height must be less that the height of the UICollectionView minus the section insets top and bottom values.
I have made sure that the size of the cell is correct
Has anyone been able to resolve this issue.
I found that, using storyboards, you have to go into the storyboard and click on the overall View Controller (the view should be highlighted in blue) and go to the Attributes Inspector (the fourth tab on the right side of the screen) and unchecking the "Under Top Bars", "Under Bottom Bars", and "Under Opaque Bars." This cleared up the issue for me, and it cleared it for my coworkers as well.
I've been having some issues when the using a collection view to present full screen view controllers.
Basically at run time, it'll ask for the size of the item and simply return the size of the collection view:
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return self.collectionView.frame.size;
}
I know this is a very late reply, but I have also experienced this.
Inside my view controller, let's call it MyViewController I have a UICollectionView that is using custom UICollectionViewCells. I'm implementing the method collectionView:layout:sizeForItemAtIndexPath where I am returning a item size that is dependent on the height of the UICollectionView.
MyViewController is made in a storyboard using autolayout to control the height of the UIViewController.
The cells look fine when in portrait mode, but did not when in landscape mode.
I solved my issues by invalidating the UICollectionViewLayout of my UICollectionView inside the viewWillLayoutSubviews method.
- (void)viewWillLayoutSubviews {
[self.myCollectionView.collectionViewLayout invalidateLayout];
}
Earlier I had tried to invalidate the layout inside willAnimateRotationToInterfaceOrientation:duration, but it didn't work. The reason for this is probably that the sizes for all the views are not calculated yet, so we have to wait until autolayout has finished its magic. I refer to this SO thread.
Update for Swift 4.0:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.myCollectionView.collectionViewLayout.invalidateLayout()
}
Had this issue myself a few times when trying to create collection views with fullscreen cells. My problem was caused by laying out for 4" screen in IB/Storyboard and specifying 320*568 for item size, but running in the simulator using 3.5" screen, which has a height of 480. The solution is to specify your item size in code with something like:
UICollectionViewFlowLayout *layout = (id) self.collectionView.collectionViewLayout;
layout.itemSize = self.collectionView.frame.size;
This ensures that the cell size is set correctly at runtime.
If you are using storyboards and auto layout, debugging this kind of problems is really hard...
I had similar problem when trying to display UICollectionViewCell fullscreen on iPhone.
Most of the time issue is with the size of the cell set in
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)
or directly on flowLayout.itemSize.
But... try:
Select the ViewController:
Then uncheck Extend Edges options:
And now try setting your auto layout constraints.
Good luck.
That fixed my problem:
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(self.collectionView.frame.size.width, self.collectionView.frame.size.height - 70);
}
U can see padding value from top and bottom on this screen:
Be sure to set the right autoresizing mask for UICollectionView and UICollectionviewcell.
This fixed my problem for iPhone 4 Simulator
For me I am using AKPickerView inside of a custom UIView which was giving me a slew of warnings like the ones mentioned here. All I did to eliminate the warnings was to Un-Check the box called 'AutoResize Subviews' in the Attributes Inspector for my custom UIView. That silenced the warnings so hard, I thought my logger stopped working.
What caused this for me was that I was trying to set my cells to the size of the superview rather than the size of the UICollectionView. Simply replaced the superview frame with the UICollectionView frame.
I had this problem when I was need full screen cells in collectionView. So I resolved it with this decision.
Cell size is equal collection view size
2. Change in storyboard "Inset from:" from Safe Area to Content Inset
Change "Content Insets" to Never
I just ran into the same error message, but for me the issue was that when I received new data from the api and tried to refresh my collectionView, the method that called [collectionView reloadData] wasn't calling it on the main thread.
Hope this helps someone...
I have same issue
the behavior of the UICollectionViewFlowLayout is not defined because:
the item height must be less than the height of the UICollectionView minus the section insets top and bottom values.
I solved this issue by checking the values in section Insets.And for fix cell size I have used below code.
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
CGSize result = [[UIScreen mainScreen] bounds].size;
CGFloat scale = [UIScreen mainScreen].scale;
result = CGSizeMake(result.width * scale, result.height * scale);
CGFloat cellWidth = [[UIScreen mainScreen] bounds].size.width - 20;
CGFloat cellHeight = [[UIScreen mainScreen] bounds].size.height - 120;
return CGSizeMake(cellWidth, cellHeight);
}
If you're loading a collectionView via a container view + UICollectionViewController, you may have set a height constraint on the container view which is constraining the height of the collection view itself. In my case, I found the collectionView.contentSize was taller than the constraint I had set on my container view.
Obviously this is a bit of an edge case but just in case you have a similar setup, I figured I'd add this comment.
For me the solution was to set Estimate Size (in the storyboard size attributes pane) for the collection view to None.
It's complaining that the item height is bigger than the height of the collectionView. So it's sticking out.
So you have to make the height the same or less.
Like this:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.height, height: collectionView.frame.height)
}
Using the height for the width makes it a square. This is assuming inset is 0 which it should be if you haven't done anything.
None of the above fixes did it for me.
I fixed it with this
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{CGFloat currentWidth = collectionView.frame.size.width;
UIEdgeInsets sectionInset = [(UICollectionViewFlowLayout *)collectionView.collectionViewLayout sectionInset]; //here the sectionInsets are always = 0 because of a timing issue so you need to force set width of an item a few pixels less than the width of the collectionView.
CGFloat width = currentWidth - 10;
}

UICollectionView's cellForItemAtIndexPath is not being called

Only my second time using UICollectionView's and perhaps I have bitten off more than I can chew but nevertheless:
I am implementing a UICollectionView (myCollectionView) that uses custom UICollectionViewCell's that I have subclassed. The subclassed cells (FullReceiptCell) contain UITableView's and are the size of the viewcontroller. I am trying to allow for horizontal scrolling between the FullReceiptCells.
The subclassed UICollectionViewController that contains myCollectionView is being pushed on to a nav controller stack. Currently, myCollectionView loas and horizontal scrolling is enabled. However, no cells are visible. I have confirmed that
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
has run and is returning an integer greater than 0. I have also confirmed that myCollectionView's delegate and datasource are properly set in IB to the subclassed UICollectionViewController.
The method where the cells are to be loaded:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
is not being called.
Here is where I push the UICollectionViewController and my viewDidLoad method within that controller (NOTE: initWithBill is an override of the normal initializer):
In the prior ViewControllers .m file:
FullReceiptViewController *test = [[FullReceiptViewController alloc] initWithBill:currentBill];
test.title = #"Review";
[self.navigationController pushViewController:test animated:YES];
In FullReceiptViewController.m:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[self.myCollectionView registerClass:[FullReceiptCell class] forCellWithReuseIdentifier:#"FullReceiptCellIdentifier"];
self.myCollectionView.pagingEnabled = YES;
// Setup flowlayout
self.myCollectionViewFlowLayout = [[UICollectionViewFlowLayout alloc] init];
[self.myCollectionViewFlowLayout setItemSize:CGSizeMake(320, 548)];
[self.myCollectionViewFlowLayout setSectionInset:UIEdgeInsetsMake(0, 0, 0, 0)];
[self.myCollectionViewFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
self.myCollectionViewFlowLayout.minimumLineSpacing = 0;
self.myCollectionViewFlowLayout.minimumInteritemSpacing = 0;
[self.myCollectionView setCollectionViewLayout:myCollectionViewFlowLayout];
//testing to see if the collection view is loading
self.myCollectionView.backgroundColor = [UIColor colorWithWhite:0.25f alpha:1.0f];
Any clue as to why it is not being called?
For those who stumble here later.... the reason:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
was not being called was because of the itemSize for the collectionViewFlowLayout's height was too big.
[self.myCollectionViewFlowLayout setItemSize:CGSizeMake(320, 548)];
If I change the height to 410, it will execute cellForItemAtIndexPath.
In my case, it was because my layout class incorrectly subclassed from UICollectionViewLayout instead of UICollectionViewFlowLayout
The cellForItemAtIndexPath will not get called if you do not provide the content size information to collection view.
If you are using Flow layout: You need to set the item sizes properly.
If you have a custom layout subclassed from UICollectionViewLayout: Ensure you are returning a proper size from the collectionViewContentSize method.
In case of the latter, you will also observe that your layoutAttributesForElementsRect is also not called. The reason is that you have not specified what is your content size and by default the size will be CGSizeZero. This basically tell collection view that you don't have any content to paint so it does not bother asking you for attributes or cells.
So, just override collectionViewContentSize and provide a proper size there, it should solve your problem.
For a more complicated view hierachy please check this blog. It saved my life!
self.automaticallyAdjustsScrollViewInsets = NO;
Maybe I'm just overlooking it, but it appears your missing your delegate and data source. In your header file, make sure you have added these:
<UICollectionViewDelegate, UICollectionViewDataSource>
and in your viewDidLoad method add this:
self.myCollectionView.delegate = self;
self.myCollectionView.dataSource = self;
Also, if you are loading it via an .xib, make sure you are have connected the IBOutlet to the UICollectionView.
If your class is subclass from UICollectionviewController and you are creating collectionView programmatically then use
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .Vertical
layout.itemSize = CGSizeMake(50, 50)
collectionView?.setCollectionViewLayout(layout, animated: false)
I was using autolayout, and in my case height constraint was missing
In my case, what I had very stupidly forgotten to do was implement the UICollectionViewDataSource protocol method numberOfItemsInSection, so that is another thing to check.
My issue was that I had 2 collection views within the same view, and both were sharing a computed UICollectionViewFlowLayout instance. Once I created separate instances of the same flow layout, it worked fine.
I was having a similar problem. But instead cellForItemAtIndexPath was called when the number of items was > 1, but not when there was only a single item. I tried many of the proposed solutions here and similar to many I found that it had to do with item sizing. For me the solution was to change the estimate size of the UICollectionView from Automatic to Custom.
In my case I had the collectionView in a UIStackView with alignment = .center. So the collectionView did not have a width. When setting the stackView.alignment to .fill everything was fine.
Ten minutes ago I also encountered this problem, I made a silly mistake.
My intention is to use UICollectionViewFlowLayout,
But because of mistakes, I used UICollectionViewLayout.
I forgot to set the autoresizing mask to false on the collection view:
collectionView.translatesAutoresizingMaskIntoConstraints = false
Also, make sure that reloadData is not called while collection view is updating with animation (insert, delete, update or performBatchUpdates).
In my case, set collectionView.prefetchingEnabled = NO; solved my problem.
Only works on iOS 10.
It was happening for me when item height == 0 by fixing that cellForItem method was called.
In my case, changing UINavigationBar's translucent to NO solved the problem.
In Xcode 7.0.1, we got this problem when we copied a storyboard and accompanying code from another project. The collection view had a custom flow layout set in the storyboard. Solution was to:
Remove the flow layout in IB
Compile/run the app
Set the flow layout back
Now it worked :)
In storyboard/xib UICollectionView property cellSize MUST not be {0, 0}
If you're using collection view protocols you must connect the CollectionViewDataSource and CollectionViewDelegate protocols to your ViewController.
Make sure numberOfSectionsInCollectionView returns a positive integer as well.
There has to be at least one section in the collection.
Make sure -(NSInteger) collectionView:numberOfItemsInSection: is returning a positive (read, greater than zero) value. It may be a matter of placing [self.collectionView reloadData]; in the completion handler.
For me, I update the height of self.view (the collectionView's superview) via autolayout, and MUST call layoutIfNeeded after that.
[self.view mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.equalTo(#(height));
}];
[self.view layoutIfNeeded];
When using UICollectionViewDelegateFlowLayout be careful on what this function returns. Both width and height should be greater than 0. I used window as frame reference but due to complicated view hierarchy window was nil at runtime. If you need adjust the width of the element based on screen width use UIScreen.main.bounds.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout:
UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {}
It can be realated layout problems. Check layout warnings from console, if exist.
In my case the collection view was not fully visible in its parent view due to wrong auto layout constraints. So fixing the constraints made the collection view all visible and cellForItemAtIndexPath was called.
Same happened to me. I had 2 UICollectionViews and I removed once since I didn't need that. After that I realised that the CellForItemAtIndexPath was not getting called but the other required methods. I tried all of the above but then I did the standard magic. Removed the collection view from storyboard and added again. Then it started working. Not sure why and I have no explanation but maybe some connection issues.
Just resolved this issue, for a somewhat specific situation.
In my case, I was manually initializing the UICollectionViewController in a parent ViewController, and then adding the UICollectionViewController's view as a subview.
I resolved the issue by calling 'setNeedsLayout' and/or 'setNeedsDisplay' on the collectionView in the parent's viewDidAppear:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[_collection.view setNeedsLayout];
[_collection.view setNeedsDisplay];
}
reloadSections instead of reloadData did it for me.
I don't know why reloadData did not work.
In my case I had to adjust the estimated Content size. content size did not do it.
let layout = collectionVC.collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSize(width: 100, height: 100)
layout.estimatedItemSize = CGSize(width: 100, height: 100)

Resources