How to render #IBDesignable UITableViewCell in Storyboard? - ios

I create a UITableViewCell subclass CustomTableViewCell and mark it as #IBDesignable. In CustomTableViewCell.xib file I drag a label to its center, then setup an #IBOutlet and name this label as contentLabel. Next, I drag a TableViewCell and put it on a ViewController's table view in the storyboard file, and change its class to CustomTableViewCell. My question is: how to render this contentLabel in the storyboard?
The following snippet doesn't work and I believe it's because contentLabel is not initialized yet in init(), but I want to give it an initial text and render it in the storyboard. How to achieve this?
#IBDesignable class CustomTableViewCell: UITableViewCell {
#IBOutlet weak var contentLabel: UILabel!
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentLabel.text = "Hello"
}
required init?(coder: NSCoder) {
super.init(coder: coder)
contentLabel.text = "Hello"
}
}
EDIT: This cell needs to reused in several different view controllers.

Related

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.

UITableViewCell outlets

When do outlets get bound to a UITableViewCell instance? If I print myLabel in the debugger, it's nil and prints:
fatal error: unexpectedly found nil while unwrapping an Optional value
class MyTableViewCell: UITableViewCell {
#IBOutlet var myLabel: UILabel!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
print("\(myLabel)")
}
}
Outlets are not yet set when the init method of your tableview cell is called!
I'm not sure what your intention is:
If you want to make sure you are not unwrapping a nil optional value just use if let like this:
if let label = myLabel {
print("\(label)")
}
If you want to setup the cell of your tableView, you should first register the cell by calling tableView.registerNib(UINib(nibName: "MyTableViewCell", bundle: nil), forCellReuseIdentifier: "reuse"). Then dequeue the cell in cellForRowAtIndexPath using tableView.dequeueReusableCellWithIdentifier("reuse") and make sure you set the values of your cell in awakeFromNib:
override func awakeFromNib() {
super.awakeFromNib()
//you can be sure that myLabel is initialzed here
print("\(myLabel)")
}
If you are connecting an outlet from the Main Storyboard, your problem could arise if the outlet was accidentally deleted. Recreate the outlet and the label will not be nil anymore.
The issue is that you are running into a case where myLabel is nil. It could be while the table view cell is being recycled.

Adding UILabel to a custom tableViewCell programmatically

I'm trying to add a label programmatically to a custom table view cell. The app will still crash with an 'unexpectedly found nil'. I've looked into other posts here but I can't see what I'm doing wrong. Please see the code for details.
import UIKit
class MyTableViewCell: UITableViewCell {
var titleLabel: UILabel!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
titleLabel = UILabel()
titleLabel.textColor = UIColor.blackColor()
titleLabel.font = UIFont.systemFontOfSize(17)
titleLabel.frame = CGRect(x: 40.0, y: 2, width: bounds.width, height: bounds.height)
addSubview(titleLabel)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
Inside the view controller:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomCell", forIndexPath: indexPath) as! MyTableViewCell
// Crashes the app with: 'fatal error: unexpectedly found nil while unwrapping an Optional value'
cell.titleLabel.text = "Some text"
}
The custom table view class is properly assigned to the prototype cell in the storyboard.
If I change the declaration inside MyTableViewCell to var titleLabel = UILabel() and delete that line from inside the init() the table view will display but my label will not show up.
The code looks good to me though, any advice as to what I may be missing here?
You made custom cell in storyboard,so you don't need to register class for table view.And views from storyboard will call initWithCoder and awakeFromNib,please add label in these two functions.

iOS UITableViewCell with custom accessoryView in InterfaceBuilder

I'm creating a settings page for my Swift app and (following examples here on SO) I've subclassed a UITableViewCell and in the init() handlers I've set the accessoryView to be a UISwitch().
I also have a custom #IBInspectable property on the subclass which is also marked #IBDesignable:
#IBDesignable class TableViewSwitchCell: UITableViewCell {
#IBInspectable var settingsKey: String?
func build()
{
accessoryView = UISwitch()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
build()
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
build()
}
// code omitted that uses the settingsKey with NSUserDefaults
}
How can I arrange for the UISwitch to also be visible in InterfaceBuilder so that I can attach additional targets to it whilst still just subclassing from UITableViewCell
Ideally I don't want to create a whole new nib with its own layout, since I still want to retain most of the other features of a standard UITableViewCell.
Drop UISwitch in Interface Builder inside of cell. Then wire it with up accessoryView of your cell. On standard basic cells the control tends to be locked in the middle of cell in IB. However in runtime it will be properly positioned.

Custom UITableViewCell on Swift

I need to create a custom UITableViewCell,
I have created a class inside of a ViewController class.
I have written the code below;
class FavoritesCell: UITableViewCell
{
var timeLabel:UILabel?
override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
super.init(style: UITableViewCellStyle.Value1, reuseIdentifier: reuseIdentifier)
timeLabel = UILabel(frame: CGRectMake(250, 10, 70, 20))
//how to add this time label as a subview of FavoritesCell
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
As i mentioned in commented line, how to add timeLabel to UITableViewCell?
Thanks
After you've created your timeLabel, this should do it:
self.contentView.addSubview(timeLabel!)
This adds the timeLabel to the cell's contentView rather than the cell itself, but that's generally what you do in table view cells.
Other things to note:
It's fine to use self here - after your super.init call, the object is fully initialised.
You've just created the timeLabel, so it's safe to force-unwrap it in addSubview.
As UITableViewCell class is derived from the UIView, so you can use the same method - self.addSubview(timeLabel!).

Resources