I try use UITableViewCell. My custom cell has StackView's and other views.
I need to send object from controller (UITableViewController) for next parsing it.
in cell I set field:
class MyCell: UITableViewCell {
var myObject : MyObject?
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
in this I try get data from my object
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
}
and in my Controller I write:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// create a new cell if needed or reuse an old one
let cell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as MyCustomCell!
cell.myObject = self.arrayMyObjects[indexPath.row]
return cell
}
But everytime I have nil in my cell. Why?
In your cell init is to early to try and access myObject. You should use a didSet on the property to make the changes when it's assigned a new value.
var myObject : MyObject? {
didSet {
// Update your subviews here.
}
}
Related
I'm putting a UITableView inside UITableViewCell.
I've extended my class of UITableViewCell to ,UITableViewDataSource, UITableViewDelegate.
Made the #IBOutlet var tableView: UITableView!
Added the following:
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style , reuseIdentifier: reuseIdentifier)
setUpTable()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
setUpTable()
}
override func awakeFromNib() {
super.awakeFromNib()
setUpTable()
}
Where as setUpTable() is implemented as:
func setUpTable(){
tableView?.delegate = self
tableView?.dataSource = self
//tableView.register(UINib(nibName: "AvailableTimingsTableViewCell", bundle: nil), forCellReuseIdentifier: "TimingCell")
}
If I keep the commented line in setUpTable() I get:
'unable to dequeue a cell with identifier TimingCell - must register a
nib or a class for the identifier or connect a prototype cell in a
storyboard'
If I uncomment the comment I get:
fatal error: unexpectedly found nil while unwrapping an Optional value
on the same line.
After setUpTable() I've implemented them as:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TimingCell", for: indexPath) as?AvailableTimingsTableViewCell
cell?.dayNameLabel.text = "Wednesday"
cell?.timeLabel.text = "01:00 PM - 03:00 PM"
return (cell)!
}
EDIT Here are the screenshots of the class names. I've double checked all is okay as per the comments and answer.
I think that setUpTable() in the init() is called too soon. At that point view is not loaded. Do that setup in viewDidLoad(), also don't comment out registering the cell. Other than that code looks good.
Please check Below points
1) You need to register cell identifier in XIB,
2) Assign Class name to XIB
3) cell for row you need to check with as? YourClass in dequeue and
4) dequeue with same identifier you assign to XIB and register (Here is issue as per me )
I put my working tableviewcontroller inside a pageviewcontroller. Now I have to register the cell in the tableview programmatically and the method awakeFromNib is not called for the cell. All properties in my custom cell are not initialized and the app crashes if I try to set content.
Is there anything different when I add a tableviewcontroller in a pageviewcontroller?
self.tableView.registerClass(ParticipantCell.self, forCellReuseIdentifier: ParticipantCell.cellIdentifier)
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let index = self.sections[indexPath.section].index+indexPath.row
let participant = self.participants[index]
let cell = tableView.dequeueReusableCellWithIdentifier(ParticipantCell.cellIdentifier, forIndexPath: indexPath) as! ParticipantCell
// cell.setParticipantData(participant)
return cell
}
If you are creating cells programmatically awakeFromNib is not called. However you can do your configurations by overriding:
init(style: UITableViewCellStyle, reuseIdentifier: String?)
As a suggestion you can have a method like this:
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupCell()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupCell()
}
func setupCell() {
// setup your cell here
}
The problem was that the Tableviewcontroller was instantiated wrong. I solved it by instantiating it from the storyboard:
let storyboard = UIStoryboard(name: "Participants", bundle: NSBundle.mainBundle())
if let controller = storyboard.instantiateViewControllerWithIdentifier("ParticipantListController") as? ParticipantListController{
...
}
I am using custom cocoa class extends from TableViewCell and it doesn't give any error message but the cells do not appear in the tableview. The scroll gets longer but the table cells are not viewable.
I typed this in my ViewController :
tableView.registerClass(CustomTableViewCell.self, forCellReuseIdentifier: "Cell")
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)->UITableViewCell
{
var cell:CustomTableViewCell? = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as? CustomTableViewCell
if cell == nil {
cell = CustomTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
}
cell!.labTime.text = filtered[indexPath.row].name!
return cell!
}
and my cell class looks like
var labTime = UILabel()
override func awakeFromNib() {
// Initialization code
super.awakeFromNib()
labTime = UILabel(frame: contentView.bounds)
labTime.font = UIFont(name:"HelveticaNeue-Bold", size: 16)
contentView.addSubview(labTime)
}
I don't use any storyBoard or xib file.
Can not find the solution,
thanks
Do this way.
All view intialization of properties should go in init method.
Add this in your custom cell class
var labTime: UILabel!
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
//Do your cell set up
labTime = UILabel(frame: contentView.bounds)
labTime.font = UIFont(name:"HelveticaNeue-Bold", size: 16)
contentView.addSubview(labTime)
}
Add the below line in viewDidLoad method of your view controller.
tableView.registerClass(CustomTableViewCell.self, forCellReuseIdentifier: "Cell")
Set these two delegate - UITableViewDataSource and UITableViewDelegate
In my custom cell swift file CustomTableView.swift, I can create programmatically the labels for my TableView but when I use IBOutlet in Storyboard the label becomes always nil
I am very sure that my cell is not nil
import UIKit
class CustomTableViewCell: UITableViewCell {
#IBOutlet weak var lblPostDate: UILabel!
var message: UILabel = UILabel()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.message.frame = CGRectMake(0, 0, 100, 40);
self.message.backgroundColor = UIColor.brownColor()
self.message.text = "bla bla bla bla bla"
self.addSubview(self.message)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
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
}
func setCell(postDate: String)
{
self.lblPostDate?.text = postDate
}
}
In the above code, the message can be seen in the cells but lblPostDate which is the IBOutlet can not be seen
I am sure about the delegate and datasource and custom cell identifier what so ever but it seems that the IBOutlets don't get initialized correctly. I can see that lblPostDate becomes nil when I debug
Is this a bug of XCode 6?
Here is how I call from my Controller
import UIKit
class HomeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var items = ["one","two","three","four"]
let kCellIdentifier: String = "CustomCell"
#IBOutlet weak var mTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.mTableView.registerClass(CustomTableViewCell.classForCoder(), forCellReuseIdentifier:kCellIdentifier)
//self.mTableView.registerClass(CustomTableViewCell.self, forCellReuseIdentifier: kCellIdentifier)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:CustomTableViewCell! = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier, forIndexPath: indexPath) as? CustomTableViewCell
if (cell == nil) {
self.mTableView.registerClass(CustomTableViewCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier)
cell = CustomTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: kCellIdentifier)
}
if var label = cell.lblPostDate{
label.text = items[indexPath.row]
}
else{
cell.setCell(items[indexPath.row])
}
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 44
}
}
You have to link the lblPostDate with one label in your cell xib file.
That is insane, I deleted the register class code and it worked, I can't believe it
//self.mTableView.registerClass(CustomTableViewCell.classForCoder(), forCellReuseIdentifier:kCellIdentifier)
After commenting out the registerClass in my Controller, it doesn't call anymore the init function but creates the lblPostDate correctly indeed
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.message.frame = CGRectMake(0, 0, 100, 40);
self.message.backgroundColor = UIColor.brownColor()
self.message.text = "bla bla bla bla bla"
self.addSubview(self.message)
}
So I don't need anymore to create hard-code input objects.
It is interesting that all the tutorials, everywhere they suggest to register the class. Anyway,it worked!
I am using the below custom UITableViewCell without nib file.
I have no problem in viewing it in my UITableViewController.
My problem is with assigning a text to "name" label cell.name.text = "a Name" .. noting is assigned
Can you help me?
import UIKit
class ACMenuCell: UITableViewCell {
#IBOutlet var name : UILabel!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
name = UILabel(frame: CGRectMake(20, 10, self.bounds.size.width , 25))
name.backgroundColor = .whiteColor()
self.contentView.addSubview(name)
self.contentView.backgroundColor = .blueColor()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func layoutSubviews() {
super.layoutSubviews()
}
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
}
}
You might want to try this: Create a public function in a subclass of UITableViewCell, and inside this funxtion set the text to label.
(void)initializeCell
{
do whatever like setting the text for label which is a subview of tableViewCell
}
And from cellForRowAtIndexPAth, call this function on cell object:
// taking your code for demo
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let reuseIdentifierAC:NSString = "ACMenuCell"; var cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifierAC, forIndexPath:indexPath) as ACMenuCell cell = ACMenuCell(style: UITableViewCellStyle.Default, reuseIdentifier: reuseIdentifierAC) [cell initializeCell] return cell }
This approach has worked for me.