Subclassing UICollectionViewCell and initialising from xib - ios

I am registering the cell like this:
collectionView!.registerNib(UINib(nibName: "ItemCell", bundle: nil), forCellWithReuseIdentifier: "ItemCellIdentifier")
and accessing it like this:
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("ItemCellIdentifier", forIndexPath: indexPath) as! ItemCell
ItemCell is the subclass of UICollectionViewCell:
class ItemCell: UICollectionViewCell {
#IBOutlet weak var itemImage: UIImageView!
#IBOutlet weak var itemImageDescription: UILabel!
//creation from nib requires this method to be overridden
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
Finally I have my xib with a UICollectionViewCell with class ItemCell.
I keep getting the error:
Assertion failure in -[UICollectionView
_dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:], /SourceCache/UIKit/UIKit-3347.44.2/UICollectionView.m:3443.
The crash is on this line:
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("ItemCellIdentifier", forIndexPath: indexPath) as! ItemCell
EDIT
collectionView!.registerNib(UINib(nibName: "ItemCell", bundle: nil), forCellWithReuseIdentifier: "ItemCellIdentifier")
is called from
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
contained in:
class CollectionCell : UITableViewCell, UICollectionViewDataSource, UICollectionViewDelegate {

Where are you calling registerNib?
I reproduced the setup to match what i can tell from yours.
This works for me, no errors :
import UIKit
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var model:[String] = []
#IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
// just a simple test model ...
for index in 1...100 {
model.append("\(index)")
}
// register the nib
collectionView.registerNib(UINib(nibName: "ItemCell", bundle: nil), forCellWithReuseIdentifier: "ItemCell")
// this is just a test layout
var layout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width:200.0,height:200.0)
layout.scrollDirection = UICollectionViewScrollDirection.Vertical
self.collectionView.collectionViewLayout = layout
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
self.collectionView.reloadData()
}
// MARK: - UICollectionViewDataSource
func collectionView(collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int{
return model.count
}
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell{
var cell:UICollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("ItemCell", forIndexPath: indexPath) as! UICollectionViewCell
return cell
}
}

Try to search in main bundle
collectionView!.registerNib(UINib(nibName: "ItemCell", bundle: NSBundle.mainBundle()), forCellWithReuseIdentifier: "ItemCellIdentifier")

The crash is because the downcasting has failed. Instead of using forced form as! use the conditional one as?
Try this other way to register cells:
ViewDidLoad
collectionView.registerClass(ItemCell.self,forCellWithReuseIdentifier:"ItemCellIdentifier")
cellForItemAtIndexPath
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath:NSIndexPath)->UICollectionViewCell
{
var cell = collectionView.dequeueReusableCellWithReuseIdentifier("ItemCellIdentifier", forIndexPath: indexPath) as ItemCell
cell.titleLabel.text="cellText"
return cell
}

Related

IBOutelt found nil when UICollectionViewCell is load

I am studying how to create a simple app without storyboard and I have a problem:
I created a XIB called HomeViewController, inside it has a UICollectioView and made the registration of the cell in the viewDidLoad().
after that, I created a cell called HomeCollectionViewCell, put the identifier as "cell", in the cell it has a UILabelOutlet, that is referenced in the .swift file.
After setting the delegate and the datasource, it has the mandatory methods of the datasource, when making the cell configuration and calling the label by setting any text it returns nil. I don't know why this is happening, I've seen several videos on YouTube and none has solved the problem. Can anybody help me?
HomeViewController
class HomeViewController: UIViewController {
#IBOutlet weak var collectionView: UICollectionView!
var info = ["Image"]
override func viewDidLoad() {
super.viewDidLoad()
collectionView.register(HomeCollectionViewCell.self, forCellWithReuseIdentifier:
"cell")
collectionView.delegate = self
collectionView.dataSource = self
}
}
extension HomeViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection
section: Int) -> Int {
return info.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath:
IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for:
indexPath) as? HomeCollectionViewCell
cell?.teste.text = "test"
return cell!
}
}
HomeCollectionViewCell
class HomeCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var teste: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
}
That's because you have to register cell's nib not just class:
collectionView.register(UINib(nibName: "HomeCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "cell")

Multiple CollectionViews in one ViewController

I try to show multiple collection views in one ViewController, but I get crash with error:
Thread 1: Exception: "could not dequeue a view of kind: UICollectionElementKindCell with identifier MainCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard"
I registered all the cells in Storyboard and this is my code for ViewController:
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var horizontalNumbers: UICollectionView!
#IBOutlet weak var verticalNumbers: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
horizontalNumbers.delegate = self
horizontalNumbers.dataSource = self
verticalNumbers.delegate = self
verticalNumbers.dataSource = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == collectionView {
return 81
} else {
return 9
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == collectionView {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MainCell", for: indexPath) as! CollectionViewCell
cell.backgroundColor = .systemGreen
return cell
} else if collectionView == horizontalNumbers {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Horizontal", for: indexPath) as! HorizontalNumbersCell
return cell
} else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Vertical", for: indexPath) as! VerticalNumbersCell
return cell
}
}
}
I checked everything twice and looked for some examples of code, but don't release why I get crash.
You need to register cell for all three collectionView.Take the collectionView for example.
try
collectionView.register(UINib(nibName: "CollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "MainCell") // if it is loaded in nib, and nib name is CollectionViewCell
or
collectionView.register(CollectionViewCell.self, forCellWithReuseIdentifier: "MainCell") // if it is written just in code
in the viewDidLoad.
Do the same thing for the horizontalNumbers, etc.
Check https://developer.apple.com/documentation/uikit/uicollectionview/1618089-register for more details.

Swift - "must register a nib or a class for the identifier or connect a prototype cell in a storyboard"

I keep getting this error message. I have already tried to add this in my code:
self.collectionView.register(UICollectionCell.self, forCellReuseIdentifier: "Cell")
But that just brings up the another error:
Ambiguous reference to member 'collectionView(_:numberOfItemsInSection:)'
Here is my code:
class HomeViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet weak var UICollectionView: UICollectionView!
let items = ["0", "1", "2", "3", "4"]
override func viewDidLoad() {
self.UICollectionView.register(CollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
super.viewDidLoad()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return items.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
cell.mainListLabel.text = items[indexPath.item]
return cell
}
}
Change
self.collectionView.register(UICollectionCell.self, forCellReuseIdentifier: "Cell")
to
self.collectionView.register(UICollectionViewCell.self, forCellReuseIdentifier: "Cell")
And
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! UICollectionViewCell
What's the CollectionViewCell stands for? It's derived class or something?
Because you register UICollectionCell but call CollectionViewCell ?
I hope it works.
// edit
Final Solution:
class CollectionViewCell: UICollectionViewCell {
#IBOutlet weak var mainListButton: UIButton!
#IBOutlet weak var mainListLabel: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.black
}
required init?(coder: NSCoder) {
super.init(coder: coder)
self.backgroundColor = UIColor.black
}
}
Set your custom collection view class or use XIB.

iOS swift custom UICollectionView with Custom Cell does not call didSelectItem

I got some issues with the following code: I created a custom Cell with a Custom UICollectionView class. I used Xib files instead of the storyboard.
It never calls the didSelectItemAtIndexPath method but why? I am really desperate :'(.
import UIKit
class CustomCollectionView: UICollectionView, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
var refreshControl : UIRefreshControl = UIRefreshControl()
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.delegate = self
self.dataSource = self
var flowLayout:UICollectionViewFlowLayout = UICollectionViewFlowLayout()
flowLayout.scrollDirection = UICollectionViewScrollDirection.Vertical
self.collectionViewLayout = flowLayout
self.refreshControl.addTarget(self, action: "refreshData:", forControlEvents: UIControlEvents.ValueChanged)
self.addSubview(refreshControl)
self.userInteractionEnabled = true
self.registerClass(CustomCollectionViewCell.self, forCellWithReuseIdentifier: "outfit")
self.registerNib(UINib(nibName: layoutHelper.getCellXibName("CustomCollectionViewCell"), bundle: nil), forCellWithReuseIdentifier: "outfit")
self.backgroundColor = UIColor.whiteColor()
}
//
// MARK: UICollectionViewDataSource - Methods
//
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
var cell : CustomCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("outfit", forIndexPath: indexPath) as! CustomCollectionViewCell
cell.label.text = "Outfit #" + String(indexPath.row)
let url = NSURL(string: "http://placehold.it/177x370")
cell.imageView.sd_setImageWithURL(url, completed: nil)
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
println("at index path %i", indexPath.row)
}

UITableView Using Swift

My TapCell1.swift
This is Custom UITableViewCell View
import UIKit
class TapCell1: UITableViewCell
{
#IBOutlet var labelText : UILabel
init(style: UITableViewCellStyle, reuseIdentifier: String!)
{
println("Ente")
super.init(style: UITableViewCellStyle.Value1, reuseIdentifier: reuseIdentifier)
}
override func setSelected(selected: Bool, animated: Bool)
{
super.setSelected(selected, animated: animated)
}
}
My ViewController.swift
Its All DataSource and Delegates are set correctly.But My custom Cell is not displaying.
import UIKit
class NextViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
{
#IBOutlet var label: UILabel
#IBOutlet var tableView : UITableView
var getvalue = NSString()
override func viewDidLoad()
{
super.viewDidLoad()
label.text="HELLO GOLD"
println("hello : \(getvalue)")
self.tableView.registerClass(TapCell1.self, forCellReuseIdentifier: "Cell")
}
func tableView(tableView:UITableView!, numberOfRowsInSection section:Int)->Int
{
return 5
}
func numberOfSectionsInTableView(tableView:UITableView!)->Int
{
return 1
}
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
{
var cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as TapCell1
cell.labelText.text="Cell Text"
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The Problem is My custom cell is Not displayed. Please suggest anything i did wrong.
Note: here is My code My File Download Link
I finally did it.
For TapCell1.swift
import UIKit
class TapCell1: UITableViewCell {
#IBOutlet var labelTitle: UILabel
init(style: UITableViewCellStyle, reuseIdentifier: String!) {
super.init(style: UITableViewCellStyle.Value1, reuseIdentifier: reuseIdentifier)
}
}
For NextViewController.swift
import UIKit
class NextViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tableView: UITableView
var ListArray=NSMutableArray()
override func viewDidLoad() {
super.viewDidLoad()
let nibName = UINib(nibName: "TapCell1", bundle:nil)
self.tableView.registerNib(nibName, forCellReuseIdentifier: "Cell")
for i in 0...70 {
ListArray .addObject("Content: \(i)")
}
}
func tableView(tableView: UITableView!, numberOfRowsInSection section: Int)->Int {
return ListArray.count
}
func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 51
}
func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
return 1
}
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as TapCell1
//cell.titleLabel.text = "\(ListArray.objectAtIndex(indexPath.item))"
cell.labelTitle.text = "\(ListArray.objectAtIndex(indexPath.row))"
return cell
}
}
My working code link: CUSTOMISED TABLE
You should register the class for the cell. For that do
change this line of code to
self.tableView.registerClass(TapCell1.classForCoder(), forCellReuseIdentifier: "Cell")
Edit
You code is looks fine i checked it
//cell.labelText.text="Cell Text"
cell.textLabel.text="Cell Text" // use like this
The solution is most likely pinpointed to setting the cell height manually as such:
override func tableView(tableView:UITableView!, heightForRowAtIndexPath indexPath:NSIndexPath)->CGFloat
{
return 44
}
I believe it's an Xcode beta 6 bug.
I have now been able to get Custom UITableViewCell to work.
Works on
Runs on Xcode 6 beta 6
Runs on Xcode 6 beta 5
iOS is 7.1
How
I have created a ".xib" file for the cell.
I copy it into the storyboard.
Via the storyboard I give it a Identifier.
I make sure it is a sub child of a tableview
Doing it this way, you do not need to register a class / nib etc.
This is my custom cell.
import UIKit
class TestCell: UITableViewCell {
#IBOutlet var titleImageView: UIImageView!
#IBOutlet var titleLabel: UILabel!
override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
In your view, or where ever you extend "UITableViewDataSource".
Make sure "cell2" is the same as the "Identifier" that you gave it via the storyboard.
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
var cell:TestCell = tableView.dequeueReusableCellWithIdentifier("cell2", forIndexPath: indexPath) as TestCell
// Example of using the custom elements.
cell.titleLabel.text = self.items[indexPath.row]
var topImage = UIImage(named: "fv.png")
cell.titleImageView.image = topImage
return cell
}
uitableviewcell
Check your Story board select the cell and look at the "identity inspector in that select CLASS type your CustomClass and MODULE type your project name
I have done this It works perfectly try this tip to avoid error to see below image and code
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell? {
// let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: nil)
// cell.textLabel.text = array[indexPath!.row] as String
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as CustomTableViewCell
cell.nameLabel.text = array[indexPath!.row] as String
cell.RestaurentView.image = UIImage(named:images[indexPath!.row])
return cell
}
Try this following code
var cell:CustomTableViewCell = tableView.dequeueReusableCellWithIdentifier("CustomTableViewCell") as CustomTableViewCell
https://github.com/iappvk/TableView-Swift
If you are not using Storyboard then create a new file as subclass of UITableViewCell check the checkbox "also create xib files" after that set your custom cell .and here is the code for tableview
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var customcell:CustomTableViewCellClass? = tableView.dequeueReusableCellWithIdentifier("cell") as? CustomTableViewCellClass
if (customcell==nil)
{
var nib:NSArray=NSBundle.mainBundle().loadNibNamed("CustomTableViewCellClass", owner: self, options: nil)
customcell = nib.objectAtIndex(0) as? CustomTableViewCell
}
return customcell!
}
Try this following code:
var cell = tableView.dequeueReusableCell(withIdentifier: "CustomCellTableView") as? CustomCellTableView
Extention of NSOject
extension NSObject {
var name: String {
return String(describing: type(of: self))
}
class var name: String {
return String(describing: self)
}
}
Properties on Custom TableViewCell
class var nib: UINib {
return UINib(nibName:YourTableViewCell.name, bundle: nil)
}
class var idetifier: String {
return YourTableViewCell.name
}
Add in UIViewController
self.tableView.registerNib(YourTableViewCell.nib, forCellReuseIdentifier: YourTableViewCell.idetifier)
let cell = tableView.dequeueReusableCellWithIdentifier(YourTableViewCell.idetifier, forIndexPath: indexPath) as! YourTableViewCell
It is Purely swift notation an working for me
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cellIdentifier:String = "CustomFields"
var cell:CustomCell? = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? CustomCell
if (cell == nil)
{
var nib:Array = NSBundle.mainBundle().loadNibNamed("CustomCell", owner: self, options: nil) cell = nib[0] as? CustomCell
}
return cell!
}

Resources