Collection view auto layout - ios

I'm making a project to show several images on a iPad, my problem is that I can't make the UICollectionView adjust to the size of the screen, and also when It rotates to landscape the auto layout does not work, I'm really lost with this, any help is very welcome.
Here is a simple example I made on Git: Git project link
Here is some code:
class ViewController: UIViewController {
#IBOutlet weak var mainMenuCollectionView: UICollectionView!
var images = ["220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg","220.jpg"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView!, numberOfItemsInSection section: Int) -> Int
{
return images.count
}
func collectionView(collectionView: UICollectionView!, cellForItemAtIndexPath indexPath: NSIndexPath!) -> UICollectionViewCell!
{
var cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as HomeCollectionViewCell
cell.imageView.image = UIImage(named:images[indexPath.row])
cell.textLabel.text = "Woof Woof"
return cell
}
}
Thanks in advance.

In you sample project you didn't set up any auto layout constraints. For example the collection view should have 4 constraints: one for each direction:
If you set all the 4 constraints to 0 it will always have the same size as it's container.
For more information you should read the apple developers guide: https://developer.apple.com/library/IOs/documentation/UserExperience/Conceptual/AutolayoutPG/Introduction/Introduction.html
Or start with some tutorials:
http://www.raywenderlich.com/50317/beginning-auto-layout-tutorial-in-ios-7-part-1

Related

My super simple UICollectionView is not loading

I'm trying to create a simple collection view. I've got my custom cell "SectionCell" and the my custom class "Section", which contains two #IBOutlet properties: titleLabel and imageView. Both of these properties are hooked up to their respective storyboard views.
In storyboard, the collectionView scene has been linked to the MenuVC.swift file, which inherits from UICollectionView. The Cell view is linked to SectionCell. And I've set the cell's Identifier to "Section".
For debugging purposes I've set the view.backgroundColor to black and the cell's contentView background color to teal. Yet when I run the the simulator neither show. I get a white background and all that appears is the view title. Any ideas on what the fix is?
class MenuVC: UICollectionViewController {
var sections = [Section]()
override func viewDidLoad() {
super.viewDidLoad()
title = "Begin Learning"
view.backgroundColor = .black
}
// MARK:- CollectionView Methods
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 3
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Section", for: indexPath) as? SectionCell else {
fatalError("Unable to dequeue SectionCell ")
}
let section = sections[indexPath.item]
cell.titleLabel.text = section.title
cell.imageView.image = UIImage(named: section.image)
return cell
}
}
class SectionCell: UICollectionViewCell {
#IBOutlet var imageView: UIImageView!
#IBOutlet var titleLabel: UILabel!
}
class Section: NSObject {
var title: String
var image: String
init(title: String, image: String) {
self.title = title
self.image = image
}
}
Simulator
I'm also quite new to posting questions on SO. If you have any tips on how to better format questions, I'm all ears!
make outlet of your collectionview and give it to the delegate and data source...
make outlet like this in your view controller:
#IBOutlet weak var collectionView: UICollectionview!
then put this code in viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
collectionView.relaodData()
}
have you implemented the following protocol?
UICollectionViewDelegateFlowLayout
extension MenuVC: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return .init(width: 300.0, height: 300.0) // and set size for each item inside this function.
}
}
SOLVED
LOL you really do need eagle eyes as a developer. This:
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 3
}
is supposed to be:
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
And voila!

UICollectionView is not appearing

When i build my project (simulator/device) UICollectionView is not appearing.
I set (i think so) all delegates,functions etc. And i still dont have that view.
class WeatherViewController: UIViewController, CLLocationManagerDelegate,UICollectionViewDelegate,UICollectionViewDataSource{
#IBOutlet weak var collectionView: UICollectionView!
var forecast: Forecast!
var forecasts = [Forecast]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
collectionView.delegate = self
collectionView.dataSource = self
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView!) -> Int{
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return forecasts.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ForecastCell", for: indexPath) as? ForecastCollectionViewCell {
let forecast = forecasts[indexPath.row]
cell.updateForecastCell(forecast: forecast)
return cell
} else {
return ForecastCollectionViewCell()
}
}
}
I downloaded the project and removed the dataSource and the delegate from storyboard because you set them already inside code.
You work with Stack Views. When I move your collectionView out of the Stack Views your code works as expected.
Unfortunately I don't know why you can't put a collectionView inside Stack View. Maybe you will find a solution then please post.
(My personal opinion: I really don't like Stack Views. It seems that they make you life easier but I can't apply with that.)

Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes

I am getting this error in my code it says to "Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger." I am confused as to what it is actually asking here is the code in which I am thinking its asking it to be put in just not sure where?
import UIKit
// MARK: - CUSTOM SOCIAL CELL
class SocialCell:UICollectionViewCell {
/* Views */
#IBOutlet weak var socialIcon: UIImageView!
#IBOutlet weak var socialLabel: UILabel!
}
class SocialList: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
/* Views */
#IBOutlet weak var socialCollView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - COLLECTION VIEW DELEGATES
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return socials.count //socialNames.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("SocialCell", forIndexPath: indexPath) as! SocialCell
cell.socialLabel.text = "\(socials[indexPath.row]["name"]!)"
cell.socialIcon.image = UIImage(named: "\(socials[indexPath.row]["name"]!)")
return cell
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake(view.frame.size.width/3.8, view.frame.size.width/3.8)
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
selectedSocial = "\(socials[indexPath.row]["link"]!)"
selectedName = "\(socials[indexPath.row]["name"]!)"
selectedColor = socialColors[indexPath.row]
navigationController?.popViewControllerAnimated(true)
}
}
You can systematically solve this by doing this:
Also, you should share your complete error, so that I can lead you to more specific issue. My thinking is that you have some sort of autoLayout issue in your UICollectionView
On the left of your project, click the Break Point navigator
Next click on the plus button on the bottom left and click Add Symbolic BreakPoint
Then you will be shown a popup. Add UICollectionViewFlowLayoutBreakForInvalidSizes in there like so
After this, just hit enter(on keyboard) and click anywhere
Run your code and see where the project stops
You can resolve this issue by setting 'Estimate size = Custom' of collectionView in size inspector.

How to arrange UICollectionVewCell from top to bottom then left to right

Question : How can I align UICollectionViewCell from top to bottom then left to right?
Current Situation : I have left to right and top to bottom which is normal behavior of it.
Check image :
MyCell.swift :
import UIKit
class MyCell: UICollectionViewCell {
#IBOutlet weak var lblCell: UILabel!
}
myCollectionVC.swift :
import UIKit
private let reuseIdentifier = "Cell"
class myCollectionVC: UICollectionViewController {
#IBOutlet weak var simpleCell: UICollectionViewCell!
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView!.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: UICollectionViewDataSource
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1 }
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//Test behavior with static number
return 100
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell: MyCell = collectionView.dequeueReusableCellWithReuseIdentifier("My_Cell", forIndexPath: indexPath) as! MyCell;
cell.backgroundColor = UIColor.greenColor();
cell.lblCell.text = String(indexPath.row + 1);
return cell
}
}
How can I cells from top to bottom then left to right?
[1][5][9][13]
[2][6][10][14]
[3][7][11][15]
[4][8][12][16]
...
...
In worst case I will try static method alignment of cells.
In my example is just a sample. Actually it must be a dynamic variable.
Just change scroll direction to Horizontal from Attribute Inspector as shown into below image:
And your result will be:

Difficulty in creating a specific layout - Swift and Xcode 6.3.2 - Single UICollectionView and then UICollectionView in UITableCell

I want to create a screen layout . A main UICollectionView class scrolling horizontally on the top 1/3 of the screen, followed by a table on the bottom 2/3, but in the table I would like to slide multiple images horizontally, so I thought of putting another collection view in the table cell. I've connected the datasource and delegate for the main collection view to the main view controller and that works. the table view is connected up to the main view controller as well.
Screenshot of IB shows what I want to do, only able to do what is shown on left. Can only implement main collectionview and underneath table.
want to create main collectionview and table with collection view in cells with headers on top of each row.
When I connect the second collectionview( the one in the table) either to the main viewcontroller or to the custom tablecell, i get various different runtime errors.
When connected to the tableview I get this error:
UITableView collectionView:numberOfItemsInSection:]: unrecognized
selector sent to instance 0x7fb009064800
My code is attached. Unfortunately, I cannot get the UICollectionview to appear in the Table.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController: UICollectionViewDataSource, UICollectionViewDelegate {
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("MainCell", forIndexPath: indexPath) as! CollectionViewCell
return cell
}
}
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("TableCell", forIndexPath: indexPath) as! TableViewCell
return cell
}
}
TableViewCell class
import UIKit
class TableViewCell: UITableViewCell {
#IBOutlet weak var subCollectionViewObject: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
extension TableViewCell: UICollectionViewDataSource, UICollectionViewDelegate {
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 15
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let subCell = collectionView.dequeueReusableCellWithReuseIdentifier("SubCell", forIndexPath: indexPath) as! SubCollectionViewCell
return subCell
}
}
import UIKit
class CollectionViewCell: UICollectionViewCell {
#IBOutlet weak var mainImage: UIImageView!
}
import UIKit
class SubCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var subImage: UIImageView!
}
Solved the issue using a scrollview inside a tableview. Easier for me to conceptualize and implement.

Resources