UICollectionView not working using swift without storyboard - ios

I am trying to set up UICollectionView in my view controller. I am created custom cell CVCell.xib. My collection view is not showing up at all. What's missing in my code?
In my viewController.swift file:
#IBOutlet var collectionViewNew: UICollectionView?
override func viewDidLoad() {
super.viewDidLoad()
self.collectionViewNew?.registerNib(UINib(nibName: "CVCell", bundle: nil), forCellWithReuseIdentifier: "CVCell")
}
func numberOfSectionsInCollectionView(
collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return 6
}
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CVCell", forIndexPath: indexPath) as CVCell
cell.backgroundColor = UIColor.orangeColor()
return cell
}

Related

Swift: CollectionView space

I have 12 cells in my CollectionView. I want to show 3 cells on one screen like this:
and scroll right to show another cells.
But now I create CollectionView and CollectionViewCell and edit cell in storyboard and I get this result:
How to fix it?
My code in CollectionView:
import UIKit
private let reuseIdentifier = "Cell"
class MasterViewController: UICollectionViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 12
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! MasterViewCell
cell.label.text = String(indexPath.row)
cell.backgroundColor = UIColor.green
return cell
}
}
My code in CollectionViewCell:
import UIKit
class MasterViewCell: UICollectionViewCell {
#IBOutlet weak var label: UILabel!
}
To achieve that spacing you need to do like so
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 4
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
so after each 3 cell in new section it will take that Section Inset and will give that space.
I have added sample screen shot for your reference please check it
and still you have confusion so please let me know.

Put UICollectionViewCell into UICollectionView

I am using LBTAComponents pod
this is a pod that makes easier to work with UICollectionView
without any need to register anything and provides a super simple anchoring system ... and in the first project I've got two days ago I decided to use this framework
but now I have a problem in one of uicollectionviewCells I need another collectionview that I can fill with items then I need it to be scrollable horizontally
import LBTAComponents
import UIKit
class ProductCell: DatasourceCell {
let cellId = "cellid"
let collectionView : UICollectionView = {
let layout = UICollectionViewFlowLayout()
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.backgroundColor = .black
return cv
}()
override func setupViews() {
super.setupViews()
ProductCell.addSubview(collectionView)
collectionView.frame = frame
collectionView.register(UICollectionView.self, forCellWithReuseIdentifier: cellId)
collectionView.dataSource = self
}
}
extension ProductCell : UICollectionViewDataSource{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
cell.backgroundColor = .white
return cell
}
}
datasourceCell is equal to UICollectionViewCell in this pod.
and now I am getting this ERROR :
instance member 'addsubview' cannot be used on type uiview did you use the value of this type instead?
could you please help me?
I tried to use self.addSubview(collectionView)
but I got another error enter image description here
You can simply use a UITableView with custom UITableViewCells containing a UICollectionView.
Example:
1. View Hierarchy
2. UIViewController containing UITableView
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate
{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
return tableView.dequeueReusableCell(withIdentifier: "tcell", for: indexPath) as! TableCell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
if indexPath.row == 0
{
return 120
}
else
{
return 150
}
}
}
3. Custom UITableViewCell containing UICollectionView
class TableCell: UITableViewCell, UICollectionViewDataSource
{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return 3
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
return collectionView.dequeueReusableCell(withReuseIdentifier: "ccell", for: indexPath)
}
}
4. Output Screenshot
addsubview is an instance method, not a class method. So you should use:
self.addSubview(collectionView)
instead of:
ProductCell.addSubview(collectionView)

UITableView inside UICollectionView -> [error] unexpectedly found nil while unwrapping tableView

I have a UITableView inside each cell of a UICollectionView.
I referenced the table view to a FeedCell class, which is a class for each cell in the collection view. However, I got an error saying
fatal error: unexpectedly found nil while unwrapping an Optional value
when trying to access the tableView object in the FeedCell class. I triple checked that I referenced the table view from the storyboard correctly, so I'm assuming there's something else that's causing it to be nil, but I'm not sure what it is. Does anyone have a clue about how to fix this?
This is my VC where both the collection view and the table view lies.
class HomeViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate,UICollectionViewDelegateFlowLayout, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.isTranslucent = false
collectionView.register(FeedCell.self, forCellWithReuseIdentifier: "FeedCell")
}
// for feedcell and its collection view
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FeedCell", for: indexPath) as! FeedCell
cell.backgroundColor = backgrounds[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
guard let collectionViewCell = cell as? FeedCell else { return }
collectionViewCell.setTableViewDataSourceDelegate(dataSourceDelegate: self, forRow: indexPath.row)
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width, height: view.frame.height)
}
// conform to tableview protocol for hometable
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return images[tableView.tag].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HomeCell", for: indexPath)
cell.imageView?.image = images[tableView.tag][indexPath.item]
return cell
}
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.setNavigationBarHidden(true, animated: animated)
super.viewWillAppear(animated)
}
override func viewWillDisappear(_ animated: Bool) {
self.navigationController?.setNavigationBarHidden(false, animated: animated)
super.viewWillDisappear(animated)
}
}
And here's a cell of the collection view where I reference the table view.
class FeedCell: BaseCollectionViewCell{
#IBOutlet weak var tableView: UITableView!
override func setupViews() {
super.setupViews()
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 4
}
}
extension FeedCell {
func setTableViewDataSourceDelegate
<D: UITableViewDataSource & UITableViewDelegate>
(dataSourceDelegate: D, forRow row: Int) {
# ERROR!
tableView.delegate = dataSourceDelegate
tableView.dataSource = dataSourceDelegate
tableView.tag = row
tableView.reloadData()
}
}
On this line:
(dataSourceDelegate: D, forRow row: Int)
You cast it as the variable: D
Use this instead:
tableView.dataSource = D
tableView.delegate = D

Populating UICollectionView with images is returning nil : Swift 2

I have a UICollectionView with a custom cell with an UIImageView in it as well as a custom class with the outlet
class theCell: UICollectionViewCell {
#IBOutlet var theImage:UIImageView!
}
I have an array of UIImage (Which only has one constant image). The image is in the main bundle.
var tempImages = [UIImage(named: "placeholder.png" )]
delegate methods
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return tempImages.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = self.collectionView?.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! theCell
//Unexpectadly found nil
cell.theImage.image = tempImages[indexPath.row]
return cell
}
If you have added this line:
self.collectionView!.registerClass(CollectionViewCell.self, forCellWithReuseIdentifier: "cell")
then remove this first and here is complete working code:
CollectionViewController.swift
import UIKit
class CollectionViewController: UICollectionViewController {
var tempImages = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
tempImages.append(UIImage(named: "bg.jpg")!)
}
// MARK: UICollectionViewDataSource
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
//#warning Incomplete method implementation -- Return the number of sections
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//#warning Incomplete method implementation -- Return the number of items in the section
return tempImages.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CollectionViewCell
// Configure the cell
cell.theImage.image = tempImages[indexPath.row]
println(cell.theImage.image)
return cell
}
}
CollectionViewCell.swift
import UIKit
class CollectionViewCell: UICollectionViewCell {
#IBOutlet var theImage:UIImageView!
}
And don't forget to assign Identifier to your cell:
Sample for more Info.
Try registering first in cellForItemAtIndexPath:
collectionView.registerNib(UINib(nibName: "FeedCell", bundle: nil), forCellWithReuseIdentifier: "cell")
EDIT
In your situation:
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
collectionView.registerNib(UINib(nibName: "FeedCell", bundle: nil), forCellWithReuseIdentifier: "cell")
let cell = self.collectionView?.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! theCell
cell.theImage.image = tempImages[indexPath.row]
return cell
}
The problem is reinitialize tempImages array so it return nil.
var tempImages = [UIImage(named: "placeholder.png" )]

How can I have multiple Collection Views in one View Controller?

I want one View Controller to have seven horizontal button scrolls. I've set up the first Collection View, and I repeated the exact process for a second Collection View directly underneath, but I keep getting Thread 1: SIGABRT error. My code for the functional Collection View is here:
class xyViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var tableImages: [String] = ["1.png", "2.png", "3.png", "4.png", "5.png", "6.png"]
override func viewDidLoad() {
// Initialize the collection views, set the desired frames
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return tableImages.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell:xyCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! xyCollectionViewCell
cell.xyImgCell.image = UIImage(named: tableImages[indexPath.row])
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
println("cell \(indexPath.row) selected")
}
}
It works when I run this.
So when I add a second Collection View underneath, create a new View Controller file to IBOutlet the button's image and a new Collection View Cell file to add the following code, it crashes.
class bwViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var bwTableImages: [String] = ["a", "PlasmaBlast.png", "b.png", "c.png", "d.png", "e.png", "f.png", "g.png", "h.png", "i.png", "j.png"]
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return bwTableImages.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell:bwCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell1", forIndexPath: indexPath) as! bwCollectionViewCell
cell.bwImgCell.image = UIImage(named: bwTableImages[indexPath.row])
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
println("cell \(indexPath.row) selected")
}
}
Here is a two-section version of the code you wrote. I'm not sure if it addresses the error you are seeing, but it's how you'd do multiple collection views on one page.
class xyViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var tableImagesOne: [String] = ["1.png", "2.png", "3.png", "4.png", "5.png", "6.png", "7.png", "8.png"]
var tableImagesTwo: [String] = ["1.png", "2.png", "3.png", "4.png", "5.png"]
override func viewDidLoad() {
// Initialize the collection views, set the desired frames
}
func numberOfSectionsInCollectionView(_ collectionView: UICollectionView) -> Int {
return 2
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if section == 0 {
return tableImagesOne.count
}
else {
return tableImagesTwo.count
}
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let row = indexPath.row
let section = indexPath.section
let cell:xyCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! xyCollectionViewCell
if section == 0 {
cell.xyImgCell.image = UIImage(named: tableImagesOne[row])
}
else if section == 1 {
cell.xyImgCell.image = UIImage(named: tableImagesTwo[row])
}
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
println("cell \(indexPath.section) : \(indexPath.row) selected")
}
}

Resources