Using custom tableViewCells created in an xib in swift - ios

I am trying to create a custom tableview cell in interface builder and use it in a tableview created in swift, the relevant code in the controller holding the tableview is as fallows:
class SearchesMainViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var contentTableView: UITableView?
override func viewDidLoad(){
super.viewDidLoad()
self.navigationItem.title = "Search"
self.contentTableView?.registerNib(UINib(nibName: "SingleSearchTableViewCell", bundle: nil), forCellReuseIdentifier: SingleSearchTableViewCellController.reuseID())
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
var cell = tableView.dequeueReusableCellWithIdentifier(SingleSearchTableViewCellController.reuseID(), forIndexPath: indexPath) as SingleSearchTableViewCellController
return cell
}
The Cell itself is very simple, 4 labels and a custom class:
class SingleSearchTableViewCellController : UITableViewCell {
#IBOutlet var dateMonthLable : UILabel?
#IBOutlet var dateDayLable : UILabel?
#IBOutlet var yearLable : UILabel?
#IBOutlet var makeModelLable : UILabel?
var search : Search
class func reuseID() -> String{
return "SingleSearchTableViewCellType"
}
override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
search = Search()
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
required init(coder aDecoder: NSCoder) {
search = Search()
super.init()
}
init(previousSearch s : Search){
search = s
super.init()
}
override init(frame: CGRect) {
search = Search()
super.init(frame: frame)
}
If I did not put enough data please feel free to ask and I thank you for your help in advance. Info on swift interacting with xib does not seem to be widely available yet.
EDIT
I have removed my custom class and the bindings for my cell look like this:
after making these changes the error reads as fallows:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key dateDayLable.'
now it looks like it is trying to bind my views to some view that is not my customUITableViewCellController

When I run into these kinds of issues it usually is caused by two things. One is that the main view in the xib file is a UIView instead of a UITableViewCell. The other is that the custom class field isn't being set to your custom class.

Check your "Datasource" and "Delegate" connections.
Check that you have added to viewController.
Check that you have properly assigned "dequeueReusableCellWithIdentifier".

Related

nib must contain exactly one top level object which must be a UITableViewHeaderFooterView instance

I am running into a weird issue when creating a customHeader for my tableView. the error that I am receiving is the following:
nib must contain exactly one top level object which must be a UITableViewHeaderFooterView instance
I ran through my code and xib file as well as examples but I couldnt find anything wrong any ideas I am missing?
The header Xib was created with a regular view and then a sub view with a label, the class was created with the following:
CustomTableHeader Class:
class CustomTableHeader: UITableViewHeaderFooterView {
static var CustomTableHeaderIdentifier = "CustomTableHeader"
#IBOutlet weak var titleLabel: UILabel!
override awakeFromNib(){
super.awakeFromNib()
self.titleLabel.text = "Header"
}
override func prepareForReuse() {
super.prepareForReuse()
}
}
ViewController Class:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(UINib.init(nibName: CustomTableHeader.CustomTableHeaderIdentifier, bundle: nil), forHeaderFooterViewReuseIdentifier: CustomTableHeader.CustomTableHeaderIdentifier)
}
//Other Methods
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: CustomTableHeader.CustomTableHeaderIdentifier) as? CustomTableHeader {
header.titleLabel.text = "Section 1"
return header
}
}
I figured out my issue! Just in case anybody ever runs into this, make sure that your first view is truly the only object in the XIB file. For example on mine I was trying to add a gesture to the header view and this is considered an object as well. If you want to add a gesture you can do so programmatically:
addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(/* FUNCTION */)))

Firebase UI custom xib and class iOS

I'm trying to figure out how to do both a custom xib and class for a tableviewcell using Firebase UI
Things I have setup in XCode:
I have a custom xib file called EventCellView.xib and
the custom tableviewcell inside of the xib has a reuse id of eventCell, it is also of the class EventTableViewCell
my code for the EventTableViewCell custom class is
class EventTableViewCell: UITableViewCell {
#IBOutlet weak var eventTitle: UILabel!
#IBOutlet weak var eventDate: UILabel!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func awakeFromNib() { super.awakeFromNib() }
}
Currently, reading the Firebase UI docs from github I've tried multiple different ways to setup my datasource, this is the one most recent one:
self.dataSource = FirebaseTableViewDataSource(ref:fbRef,
nibNamed: "EventCellView",
cellReuseIdentifier: "eventCell",
view: self.eventTable)
self.dataSource!.populateCellWithBlock { (cell: UITableViewCell, obj: NSObject) -> Void in
let snap = obj as! FDataSnapshot
var customCell = cell as! EventTableViewCell
customCell.eventTitle.text = snap.key
}
Basically per the instructions on Github it says to subclass UITableViewCell and to implement the init (style, resuseId) method, I then specify the cellResuseIdentifier and nib inside of the datasource and I get the following error:
Terminating app due to uncaught exception `NSInternalInconsistencyException`, reason:
invalid nib registered for identifier (eventCell)
- nib must contain exactly one top level object which must be a UITableViewCell instance
Any help would be awesome, thank you.

Custom UITableviewCell IBOutlet always nil

I have a custom UITableViewCell subclass with a simple IBOutlet setup for a UILabel.
class SegmentCell: UITableViewCell {
#IBOutlet weak var test: UILabel!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
test.text = "Some Text"
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Convinced I have everything set up correct have followed other answers, but the UILabel is always nil.
ViewController:
viewDidLoad:
self.tableView.registerClass(SegmentCell.self, forCellReuseIdentifier: "Cell")
cellForForAtIndexPath
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! SegmentCell
return cell
}
Cell is set to Custom
Reuse identifier is correct
Cells class is SegmentCell
Tableview content is Dynamic Prototypes
What am I missing?
Since You are uisg Xib file you have to register with ,
tableView.register(UINib(nibName: "yourNib", bundle: nil), forCellReuseIdentifier: "CellFromNib")
Think, if only register with class ,system will not know the its Xib.This work for me.
Based on the way you register your cell, it is not going to be loading it from a storyboard or xib file. It will be invoking that init method only. Your init method does not create the label, so it will always be nil.
You should also use dequeueReusableCellWithIdentifier(_:forIndexPath:) instead of dequeueReusableCellWithIdentifier(_:). The latter predates storyboards and will return nil unless you have previously created a cell with that identifier and returned it.
Lastly, the init method that the tableView is calling is not the one you've implemented, or the app would crash on test.text = ... while trying to unwrap a nil optional.
UITableViewCell class and ContentView class can't be same.
You should register it first in the viewDidLoad function.
self.tableView.registerClass(CustomCell.self, forCellReuseIdentifier: "Cell")
I have same issue, after add custom cell class to cell in tableview placed in Storyboard.
I also register cell, like in documentation. But now I solve my issue.
"I remove registering and inspect cell again, all IBOutlets initialised"
I think that basically the outlets are not setup yet at init time. If you want to get to the outlets and manipulate them, then override didMoveToSuperview or similar and do it in there. For instance, this is what I had to do to get to the button outlet in my cell:
open class MyTableViewCell: UITableViewCell {
// Top stack view, not the inner one.
#IBOutlet weak var stackView: UIStackView!
#IBOutlet weak var buttonView: UIButton?
open override func didMoveToSuperview() {
buttonView?.titleLabel?.adjustsFontForContentSizeCategory = true
}
func adjustForAccessibilityCategory(accessible: Bool) {
if accessible {
stackView.axis = .vertical
stackView.alignment = .leading
stackView.spacing = 2
} else {
stackView.axis = .horizontal
stackView.alignment = .center
stackView.spacing = 20
}
}
open override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
if #available(iOS 11.0, *) {
adjustForAccessibilityCategory(accessible: traitCollection.preferredContentSizeCategory.isAccessibilityCategory)
}
}
}

How to access custom cell created in xib

I have designed a custom cell in xib. And created a class for that as well. The code for that class is as given below-
class ProjectsCell : UITableViewCell {
#IBOutlet var projectNameLabel: UILabel! //This is outlet to which I will assign value.
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
}
}
Now I have a view controller there I am trying to access this cell. In storyboard I have given reusable identifier "Cell". Now I am using this cell like the following code-
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as ProjectsCell
let project = projects[indexPath.row]
cell.projectNameLabel?.text = project.ProjectName //********* Here I am getting exception for projectNameLabel.
return cell
I think that label is coming null. I have tried the following approach also but that is also not working.
var cell: ProjectsCell = tableView.dequeueReusableCellWithIdentifier("Cell") as ProjectsCell
tableView.registerNib(UINib(nibName: "ProjectsCell", bundle: nil), forCellReuseIdentifier: "Cell")
cell = tableView.dequeueReusableCellWithIdentifier("Cell") as ProjectsCell
What can be the issue if anyone has faced this same issue.
Your custom cell should inherit from the class UITableViewCell. So the class would look like this.
class ProjectsCell: UITableViewCell {
#IBOutlet var projectNameLabel: UILabel! //This is outlet to which I will assign value.
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
}
}
If you have it like this it should work. Because i am doing it like that in my Apps. For the future if you create a class you can use the 'File -> New Files...' menu. There you can select coca touch class and specify the class you want to inherit from and xcode will add all necessary functions.
You have dequeued the custom cell but not initialised it with the following method.
Besides this you also have to set your custom class as the sub-class of UITableViewCell this is because you are getting the null value for the cell.
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStylePlain reuseIdentifier: "Cell")
}
I solved the problem using the following code-
var array = NSBundle.mainBundle().loadNibNamed("ProjectsCell", owner: self, options: nil)
var cell = array[0] as ProjectsCell
let project = projects[indexPath.row]
cell.nameLabel?.text = project.Name
return cell
Thanks everyone for contributing. :)
Maybe it set the dataSource and delegate :
(source: icodeblog.com)

UILabels not updating in custom prototype cell of UITableViewController

Have tried several variations and watched different tutorials but cannot get my custom prototype cell to change from the defaulted text "label" in my tableviewcontroller. I have defined these labels as IBOutlets in the custom prototype file which is appropriately linked. I'm sure I missing something elementary here. Any thoughts?
import UIKit; import Parse
class UserRecordsTableViewController: PFQueryTableViewController {
// Initialise the PFQueryTable tableview
override init!(style: UITableViewStyle, className: String!) {
super.init(style: style, className: className)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
// Configure the PFQueryTableView
self.parseClassName = "Event"
self.textKey = "category"
self.textKey = "duration"
self.pullToRefreshEnabled = true
self.paginationEnabled = false
}
// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery! {
var query = PFQuery(className: "event")
query.orderByAscending("category")
return query
}
//override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject) -> PFTableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as UserRecordsTableViewCell!
if cell == nil {
cell = UserRecordsTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
}
// Extract values from the PFObject to display in the table cell
cell.durationEventLabel.text = object["duration"] as? String
// Date for cell subtitle
return cell
}
}
Here is my cell:
import UIkit
class UserRecordsTableViewCell: PFTableViewCell {
#IBOutlet weak var dateEventLabel: UILabel!
#IBOutlet weak var catEventLabel: UILabel!
#IBOutlet weak var durationEventLabel: UILabel!
}
And under class in IB I have selected UserRecordsTableViewCell.
I have decided the best approach to my desired look is to go with PFTableViewCell provided by parse framework and simply only show two items. Main category and date as subtitle. This is opposed to creating a custom cell which works well with text and image label but not well with two text keys. Followed this tutorial and was great:
https://medium.com/swift-programming/ios-swift-parse-com-tutorial-set-up-xcode-project-part-2-of-3-31a17d1c6581

Resources