Reputation: 1835
The goal is to use a common XIB file to display a variety of objects. To do so, I have created the XIB and connected it's IBOutlets to the UITableView subclass, MyCustomCell
class MyCustomCell:UITableViewCell {
@IBOutlet weak var myLabel:UILabel!
}
This cell should be capable of displaying data from two types of objects and it enhances convenience to have the cell handle it's own population rather than access myLabel
from the tableViewDelegate, so two separate subclasses are needed:
class ObjectTypeATableViewCell:MyCustomCell {
var record:ObjectTypeA! {
didSet {
myLabel.text = record.name
}
}
}
class ObjectTypeBTableViewCell:MyCustomCell {
var record:ObjectTypeB! {
didSet {
myLabel.text = String(record.totalQty)
}
}
}
It all builds fine. The issue, however, comes with reusing the cell on the TableView. Below is the implementation of this I am working with.
class MyTable: UITableView, UITableViewDataSource {
var records:Array<AnyObject>()
/// Run when the tableView is loaded
func xibSetup() {
let nib = UINib(nibName: "MyCustomCell", bundle: nil)
registerNib(nib, forCellReuseIdentifier: "recordCell")
dataSource = self
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let object = sectionedItems().itemsInSections[indexPath.section][indexPath.row]
if let i = object as? ObjectTypeA {
let cell = dequeueReusableCellWithIdentifier("recordCell") as! ObjectTypeATableViewCell
cell.record = i
return cell
} else if let i = object as? ObjectTypeB {
let cell = dequeueReusableCellWithIdentifier("recordCell") as! ObjectTypeBTableViewCell
cell.record = i
return cell
} else {
let cell = UITableViewCell()
cell.textLabel?.text = "unknown object type."
return cell
}
}
}
A fatal error is occurring when the cell is dequeued:
Could not cast value of type 'MyProject.MyCustomCell' (0x10ade39e0) to 'MyProject. ObjectTypeATableViewCell' (0x10ade3e20).
How can the cell be properly cast as a subclass?
Upvotes: 0
Views: 1686
Reputation: 137
Dont need to subclass MyCustomCell, you can declare a protocol to use like this:
protocol ObjectTypeProtocol {
func getText() -> String
}
class ObjectTypeA : ObjectTypeProtocol{
var name = "name of ObjectTypeA"
//....
func getText() -> String {
return name
}
}
class ObjectTypeB : ObjectTypeProtocol{
var totalQty = "total of ObjectTypeB"
//....
func getText() -> String {
return String(totalQty)
}
}
class MyCustomCell: UITableViewCell {
@IBOutlet var myLabel:UILabel!
var record:ObjectTypeProtocol! {
didSet {
myLabel.text = record.getText()
}
}
}
Upvotes: 2
Reputation: 442
Try to change the tableView regist class like this :
tableView.registerClass(ObjectTypeATableViewCell.self, forCellReuseIdentifier: "ObjectTypeATableViewCell")
To solve your problem maybe you should creating another custom view instead, just named "MyCustomCellContentView", and it inherit from UIView
, also create a xib file named "MyCustomCellContentView". Set the xib class
"MyCustomCellContentView"
After the step, you should move views in MyCustomCell
to MyCustomCellContentView
, and then delete theMyCustomCell.xib
file. Link the label in MyCustomCellContentView
. Change your code @IBOutlet weak var myLabel:UILabel!
with var myLabel : UILabel?
Then override init(style: UITableViewCellStyle, reuseIdentifier: String?)
in MyCustomerCell
:
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
let nib = NSBundle.mainBundle().loadNibNamed("MyCustomCellContentView",owner: nil, options: nil).first
let view = nib as! MyCustomCellContentView
myLabel = view.label
contentView.addSubview(view)
}
At last, override layoutSubViews
:
override func layoutSubviews() {
super.layoutSubviews()
label!.superview!.frame = self.bounds
}
Upvotes: 0