UICollectionView is not appearing - ios

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

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!

How to organise dynamic number of uitableview as swiping pages in swift

There is a dynamic set of data i have to organise as set of swiped tables. Now I'm using UIPageViewController for this task, but it has some problems with dynamically uploaded data from net - if we swiping pages too fast, we can overtake data loading and program can crashes. Now, to solve this problems, i'm uploading data in advance of 5 pages, but i think it's bad solution and i hope there is a right solving for this task.
I found another idea - using UICollectionView for this task, but i'm not sure, that i can use tables as UICollectionViewCell in this method and i'm not sure, that this decision is correct.
What can you recommend in this situation
here is my approach to such case
first I would have my ViewController containing the collectionView as below -make sure to add your own constraints however you would like-
import UIKit
class ViewController: UIViewController {
// IBOutlets
#IBOutlet var collectionView: UICollectionView!
// MARK: Lifecycle Methods
override func viewDidLoad() {
super.viewDidLoad()
setupCollectionView()
}
// MARK: Private Methods
private func setupCollectionView(){
collectionView.delegate = self
collectionView.dataSource = self
collectionView.separatorStyle = .none
collectionView?.register(UINib(nibName: /* Your cell NibName */, bundle: nil), forCellWithReuseIdentifier: /* Your cell Id*/)
collectionView?.isPagingEnabled = true
}
// MARK: UICollectionView Methods
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return zekr?.subNodes?.count ?? 0
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = zekrCollectionView.dequeueReusableCell(withReuseIdentifier: /* Your cell Id */, for: indexPath) as! /* Your cell Type */
cell.cellData = /* your list that corresponds with the list that table will take */
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// this is to make each cell fill the whole page
return CGSize(width: view.frame.width, height: view.frame.height)
}
}
then you will add tableview inside each collectionViewCell and for sure to fulfill the delegate and datasource for the tableView inside the collectionViewCell as below
import UIKit
class CollectionViewCell: UICollectionViewCell, UITableViewDataSource, UITableViewDelegate {
// MARK: IBOutlets
#IBOutlet weak var pageTable: UITableView!
var cellData: [/*Your List*/]?
// MARK: Properties
var cellData: /*Your List*/?{
didSet{
if let value = cellData {
/* reload your table */
}
}
}
// MARK: Life Cycle Methods
override func awakeFromNib() {
super.awakeFromNib()
setupPageTable()
}
private func setupPageTable(){
pageTable.delegate = self
pageTable.dataSource = self
pageTable.register(UINib(nibName: /* TableView Cell NibName */, bundle: nil), forCellReuseIdentifier: /* CellId */)
}
// MARK: UITableViewDelegate
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellData?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: /* CellId */) as! /* Cell Type */
cell.cellDataModel = cellData?[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let cell: UITableViewCell = cellData?[indexPath.row]
return cell.contentView.frame.size.height
}
}
and finally your tableViewCell will remain as the same however you done it initially passing to it the cellDataModel
in case the horizontal scrolling did't work for the collectionView you can google a solution depending on your swift version
the result you will be having collectionView on your home or whatever VC you are on with horizontal scrolling each cell containing tableView with it's cells with vertical scrolling acting as viewPager in android

UICollectionView not rendering cells - no code only storyboard

I am experimenting with UICollectionView and am only using Storyboard - no code at all. I set the number of items to 3 and gave each cell a different color and reuse identifier in the storyboard. Yet the CollectionView (pinkish background) is shown but no cells are shown. What am I missing?
Thanks in advance
-SR
Short Answer
UICollectionView doesn't support static content layouts.
Discussion
But there is a way to simulate it through code. I recommend this great article.
You don't have any code in your ViewController.swift. You can add something like this:
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var menuItems = ["Aap","Koe","Vis","Paard", "Leeuw", "Varken"]
#IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return menuItems.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
if let c = cell as? AangepasteCollectionViewCell {
c.cellLabel.text = menuItems[indexPath.row].capitalized
}
return cell
}
}
For this example you have to give the collection cell the name cell in the atribute inspector

Using CollectionView in UIView with xib file

i'm doing with this, i want to use CollectionView, but i haven't seen prototype cell, and don't know how to use CollectionView in this case, can someone help me ?
I try to use like this way but it take alot of time and hard to manage than UICollectionView
The main way to use UICollectionView is by managing the logic programmatically.
First, create a new class which inherits from UICollectionViewCell. Choose if you want to include a xib to easily design your cell:
Design your cell with Interface Builder or programmatically.
Create your main view controller including a xib (or a storyboard) with the collection view inside and link it to the associated class via Interface Builder. Alternatively you can add a collection view programmatically to your UIViewController
Make the target view controller conform to the UICollectionViewDelegate and UICollectionViewDataSource protocols by declaring them after the father class:
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
//...
}
Register the associated nib or the class for your cell in the viewDidLoad method and associate the datasource and delegate protocols to the view controller class:
let cellIdentifier = "cellIdentifier"
override func viewDidLoad() {
super.viewDidLoad()
//if you use xibs:
self.collectionView.register(UINib(nibName:"MyCollectionCell", bundle: nil), forCellWithReuseIdentifier: cellIdentifier)
//or if you use class:
self.collectionView.register(MyCollectionCell.self, forCellWithReuseIdentifier: cellIdentifier)
self.collectionView.delegate = self
self.collectionView.dataSource = self
}
Implement the methods declared in the UICollectionViewDelegate and UICollectionViewDataSource protocols :
let objects = ["Cat", "Dog", "Fish"]
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.objects.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! MyCollectionCell
//in this example I added a label named "title" into the MyCollectionCell class
cell.title.text = self.objects[indexPath.item]
return cell
}
Run your app in the simulator (or on a real device) and.. Et voilĂ ! :)
For more info: https://developer.apple.com/reference/uikit/uicollectionview
ok first you must have the IBOutlet of your collection view and implements the methods like this
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource,UICollectionViewDelegateFlowLayout{
#IBOutlet var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
count = 9;
let nib = UINib(nibName: "yourItemView", bundle: nil)
collectionView.registerNib(nib, forCellWithReuseIdentifier: "yourItemView")
self.collectionView.delegate = self
self.collectionView.dataSource = self
}
ok in the function you add a xib file, next you must create that extend from UICollectionViewCell, and when you finish this you must override the next methods
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return count
// the numbers of items
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {//size of your item for screen sizes
let wsize = UIScreen.mainScreen().bounds.size.width
switch(wsize){
case 414:
return CGSize(width: 190, height: 102)
case 375:
return CGSize(width: 190, height: 102)
case 320:
return CGSize(width: 174, height: 102)
default:
return CGSize(width: 174, height: 102)
}
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("yourItemView", forIndexPath: indexPath) as! yourItemView
return cell
}
and this is all, good luck

Collection view auto layout

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

Resources