Generic UITableViewCell Identifier - ios

I try to use types and enum instead of string for the cellIdentifier
I don't want to use the cell class name as identifier since I can have multiple Identifiers for one type cell (for example the basic cell in different tableviews)
enum TableViewCellIdentifier: String {
case formCell, questionCell
// Here I can have the type, and I want to use it to ensure the cell dequeued by the identifier is the right type
var typeCell: UITableViewCell.Type {
switch self {
case .formCell:
return UITableViewCell.self
case .questionCell:
return QuestionCell.self
}
}
// I could use an extension of UITableView to build an other version of dequeueCell,
// but I'll choose after it the type constraint will let me choose.
// Here I want to constraint the return type with the value of myValue.typeCell
func dequeueCell(with tableView: UITableView, for indexPath: IndexPath) -> UITableViewCell {
return tableView.dequeueReusableCell(withIdentifier: self.rawValue, for: indexPath)
}
// func dequeueCell<T: self.typeCell>(with tableView: UITableView, for indexPath: IndexPath) -> T {
// return tableView.dequeueReusableCell(withIdentifier: self.rawValue, for: indexPath) as! T
// }
}
Any Ideas ?
Thanks !

import Foundation
import UIKit
protocol Reusable: class{
static var reuseIdentifier: String { get }
}
extension Reusable {
static var reuseIdentifier: String {
return String(describing: self)
}
}
extension UITableViewCell: Reusable{}
extension UITableViewHeaderFooterView: Reusable{}
protocol NibLoadableView {
static var nibName: String { get }
}
extension NibLoadableView {
static var nibName: String {
return String(describing: self)
}
}
extension UITableViewCell: NibLoadableView {}
extension UITableView {
func register<T: UITableViewCell>(_: T.Type) {
register(T.self, forCellReuseIdentifier: T.reuseIdentifier)
}
func registerNib<T: UITableViewCell>(_: T.Type) {
let bundle = Bundle(for: T.self)
let nib = UINib(nibName: T.reuseIdentifier, bundle: bundle)
print(T.nibName, T.reuseIdentifier)
register(nib, forCellReuseIdentifier: T.reuseIdentifier)
}
func registerHeaderNib<T: UITableViewHeaderFooterView>(_: T.Type) {
let bundle = Bundle(for: T.self)
let nib = UINib(nibName: T.reuseIdentifier, bundle: bundle)
print(T.reuseIdentifier, T.reuseIdentifier)
register(nib, forHeaderFooterViewReuseIdentifier: T.reuseIdentifier)
}
func dequeueReusableCell<T: UITableViewCell>(for indexPath: IndexPath) -> T {
print(T.reuseIdentifier)
guard let cell = dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as? T else {
fatalError("Could not dequeue cell with identifier: \(T.reuseIdentifier)")
}
return cell
}
func dequeueReusableHeaderFooterView<T: UITableViewHeaderFooterView>(for section: Int) -> T {
print(T.reuseIdentifier)
guard let cell = dequeueReusableHeaderFooterView(withIdentifier: "DemoHeaderView") as? T else {
fatalError("Could not dequeue cell with identifier: \(T.reuseIdentifier)")
}
return cell
}
}
This is how ViewContoller will use it.
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(TestCell.self)
let headerNib = UINib.init(nibName: "DemoHeaderView", bundle: Bundle.main)
tableView.register(headerNib, forHeaderFooterViewReuseIdentifier: "DemoHeaderView")
tableView.registerHeaderNib(DemoHeaderView.self)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
}
extension ViewController: UITableViewDataSource, UITableViewDelegate {
// MARK: - UITableView delegate
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: TestCell = tableView.dequeueReusableCell(for: indexPath)
cell.textLabel?.text = "\(indexPath.row)"
return cell
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = tableView.dequeueReusableHeaderFooterView(for: section)
return headerView
}
}

Related

Make different collapsable sections in tableView swift iOS

I want to implement the different expand/collapse section in tableView and each sections contain the different kind of data.I'm getting the index of section when user click on button. Now i want when user click on button section collapse and expand.Initially first time all sections data should be hidden when user first time comes. See my code and screenshot.
ViewController Code:
enum ProfileItems: Int{
case namePicture = 0
case about = 1
}
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var items:[ProfileItems] = [.namePicture, .about]
var profile:[Profiles] = [
Profiles(name: "Ki", profileImage: "slide2"),
Profiles(name: "Kaleem", profileImage: "slide3"),
Profiles(name: "Jameel", profileImage: "slide2")
]
var about: [About] = [
About(title: "Johns"),
About(title: "Dons")
]
var isHiddenSection: Bool = false {
didSet {
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
registerCell()
}
func registerCell() {
tableView.delegate = self
tableView.dataSource = self
tableView.register(UINib(nibName: String(describing: PictureTvCell.self), bundle: .main), forCellReuseIdentifier: String(describing: PictureTvCell.self))
tableView.register(UINib(nibName: String(describing: AboutTVCell.self), bundle: .main), forCellReuseIdentifier: String(describing: AboutTVCell.self))
tableView.register(UINib(nibName: String(describing: HeaderTVCell.self), bundle: .main), forCellReuseIdentifier: String(describing: HeaderTVCell.self))
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: HeaderTVCell.self)) as? HeaderTVCell else {return UIView()}
switch items[section]{
case .namePicture:
cell.lableName.text = "Info"
case .about:
cell.lableName.text = "Collection"
}
cell.buttonCollpase.tag = items[section].rawValue
cell.delegate = self
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch items[section] {
case .namePicture:
return profile.count
case .about:
return about.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch items[indexPath.section] {
case .namePicture:
return configurePictureCell(tableView, cellForRowAt: indexPath)
case .about:
return configureAboutCell(tableView, cellForRowAt: indexPath)
}
}
func configurePictureCell(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PictureTvCell.self)) as? PictureTvCell else {return UITableViewCell()}
cell.profiles = self.profile[indexPath.row]
return cell
}
func configureAboutCell(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: AboutTVCell.self)) as? AboutTVCell else {return UITableViewCell()}
cell.about = self.about[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 40
}
}
extension ViewController: CollpaseSection {
func getIndex(_ index: Int) {
switch items[index] {
case .namePicture:
print("picture")
case .about:
print("about")
tableView.reloadData()
}
}
}
TableViewHederCell Code:
protocol CollpaseSection:AnyObject {
func getIndex(_ index: Int)
}
class HeaderTVCell: UITableViewCell {
#IBOutlet weak var lableName: UILabel!
#IBOutlet weak var buttonCollpase: UIButton!
weak var delegate: CollpaseSection?
#IBAction func didTapCollapse(_ sender: UIButton) {
delegate?.getIndex(sender.tag)
}
}
Screenshot current output:
enter image description here

Using a completion handler in another class/extension

I have a class, LocationViewController, which needs to implement a TableView. I have a function getParsedTestingLocation() which uses a completion handler from another function to get some data.
class LocationViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func getParsedTestingLocations(completion: #escaping ([TestingLocation]?, Error?) -> (Void)) {
getTestingLocationsJSON(completion: { testLocationsJSON, error in
if let testLocationsJSON = testLocationsJSON {
let testLocationsData = Data(testLocationsJSON.utf8)
let decoder = JSONDecoder()
do {
let testLocations = try decoder.decode([TestingLocation].self, from: testLocationsData)
completion(testLocations, nil)
} catch {
print(error)
}
}
})
}
}
I want to use the value testLocations within getParsedTestingLocations() in an external extension in this file. Here are the extensions I have:
extension LocationViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("you tapped me!")
}
}
extension LocationViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = "empty cell"
return cell
}
}
Within all 3 tableView() functions I want to get the values stored in testLocations in the completion handler in these functions. How could I do this?
Actually you don't need a completion handler. Reload the table view inside the completion closure of the API call
class LocationViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var locationData = [TestingLocation]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
getParsedTestingLocations()
}
func getParsedTestingLocations() {
getTestingLocationsJSON(completion: { testLocationsJSON, error in
if let testLocationsJSON = testLocationsJSON {
let testLocationsData = Data(testLocationsJSON.utf8)
let decoder = JSONDecoder()
do {
self.locationData = try decoder.decode([TestingLocation].self, from: testLocationsData)
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch {
print(error)
}
}
})
}
}
extension LocationViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return locationData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let location = locationData[indexPath.row]
cell.textLabel?.text = location.whatEverStringYouWantToDisplay
return cell
}
}
Replace whatEverStringYouWantToDisplay with the real struct member name.
You don't need a completionHandler in getParsedTestingLocations in this case as the function already calls a function which has completionHandler. Just use a variable
class LocationViewController: UIViewController {
private lazy var locationArr = [TestingLocation]()
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
getParsedTestingLocations()
}
func getParsedTestingLocations() {
getTestingLocationsJSON(completion: { testLocationsJSON, error in
if let testLocationsJSON = testLocationsJSON {
let testLocationsData = Data(testLocationsJSON.utf8)
let decoder = JSONDecoder()
do {
let testLocations = try decoder.decode([TestingLocation].self, from: testLocationsData)
self.locationArr = testLocations
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch let error {
//Show Alert
}
}
})
}
}
extension LocationViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return locationArr.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = locationArr[indexPath.row].variable
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("you tapped me! \(locationArr[indexPath.row])")
}
}

Custom xib cells are not appearing on UITableView swift

my cells are not appearing.
I did:
Checked if datasource and delegate were connected
Checked if my custom cells identifier name and class were correct
Things that I didn't:
I am struggling with auto layout, so I just decided not to do it.
My app is loading with the correct amount of cells, but the cells are not registered.
My code:
import UIKit
class WelcomeViewController: UITableViewController, NetworkManagerDelegate {
private var networkManager = NetworkManager()
private var infoForCells = [Result]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(UINib(nibName: "ImageViewCell", bundle: nil), forCellReuseIdentifier: "imageCell")
networkManager.delegate = self
networkManager.fetchNews()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return infoForCells.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "imageCell", for: indexPath) as? ImageViewCell else{
return UITableViewCell(style: .default, reuseIdentifier: "cell")
}
let cellIndex = infoForCells[indexPath.row]
cell.titleForImage.text = cellIndex.alt_description
print(cell.titleForImage ?? "lol")
// if let image = cellIndex.urlToImage {
// cell.imageForArticle.load(url: image)
// }
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
func didUpdateNews(root: Root) {
infoForCells = root.results
}
}
Reload the table
func didUpdateNews(root: Root) {
infoForCells = root.results
tableView.reloadData()
}
In addition to Sh_Khan answer you can also listen to updates of infoForCells property
private var infoForCells = [Result]() {
didSet {
DispatchQueue.main.async { [weak self] in
self?.tableView.reloadData()
}
}
}

how to make model,viewmodel from the url

how to make model,viewModel and DataSourceModel for this type of api.
{"data":[{"id":45,"question":"Were the answers that staff provided to your questions presented in a way that you could understand?","options":["Yes, always","Yes, sometimes","No""Other"]}]}
this is my api.
According to my design i am using tableview section So in the header the questions will display and in the tableviewcell the list of options will display.
output as :-
Were the answers that staff provided to your questions presented in a way that you could understand?
Yes, always
Yes, sometimes
No
Other
this way i need to display.
My code is as below:-
model:-
classQuestionListModel: NSObject {
var home:[OPTIONS] = []
var id:String?
var question:String?
var options:[String]?
var v:String?
init?(dictionary :JSONDictionary) {
guard
let question = dictionary["question"] as? String,
let id = dictionary["id"] as? String
else {
return
}
if let options = dictionary["options"] as? [String]{
print(options)
}
self.question = question
self.id = id
}
}
viewmodel:-
func numberOfSections(tableView: UITableView) -> Int{
print((datasourceModel.dataListArray?.count)!)
return (datasourceModel.dataListArray?.count)!
}
func titleForHeaderInSection(atsection section: Int) -> QuestionListModel {
return datasourceModel.dataListArray![section]
}
func numberOfRowsInSection(section:Int) -> Int {
print(self.tableArray[section].count)
return self.tableArray[section].count
}
func datafordisplay(atindex indexPath: IndexPath) -> OPTIONS{
// print(datasourceModel.dataListArray![indexPath.section].options)
return datasourceModel.dataListArray![indexPath.row]
// return values
}
in viewcontroller:-
func numberOfSections(in tableView: UITableView) -> Int {
return reviewViewModel.numberOfSections(tableView: tableView)
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let identifier = "HeaderCell"
var headercell: questionheader! = tableView.dequeueReusableCell(withIdentifier: identifier) as? questionheader
if headercell == nil {
tableView.register(UINib(nibName: "questionheader", bundle: nil), forCellReuseIdentifier: identifier)
headercell = tableView.dequeueReusableCell(withIdentifier: identifier) as? questionheader
}
headercell.setReviewData(reviews:reviewViewModel.titleForHeaderInSection(atsection:section))
headercell.setReviewData(reviews:reviewViewModel.datafordisplay(atindex: section))
return headercell
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 63
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return reviewViewModel.numberOfRowsInSection(section: section)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let identifier = "Cell"
var cell: QuestionListCell! = tableView.dequeueReusableCell(withIdentifier: identifier) as? QuestionListCell
if cell == nil {
tableView.register(UINib(nibName: "QuestionListCell", bundle: nil), forCellReuseIdentifier: identifier)
cell = tableView.dequeueReusableCell(withIdentifier: identifier) as? QuestionListCell
}
cell.contentView.backgroundColor = UIColor.clear
cell.question.text = reviewViewModel.datafordisplay(atindex: indexPath)
print(reviewViewModel.tableArray)
return cell
}
in questionlistcell:-
class
QuestionListCell: UITableViewCell {
#IBOutlet weak var imagebutton: UIButton!
#IBOutlet weak var options: UILabel!
var i = 0
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func setReviewData(reviews:QuestionListModel)
{
print(reviews.options)
self.question.text = reviews.v
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
cell.question.text is expecting a string, & you passed QuestionListModel.
It should be
if let question = reviewViewModel.datafordisplay(atindex: indexPath).question {
cell.question.text = question
}

Dependency injection in uitableviewcell nibs

I'm trying to build a pretty complex table. One cell of this table imports another table. In this imported table I show different rows depending on the situation. The imported table and all the importable table cells are organized into own nib files with own controllers for every cell. As a good programmer I'm trying to use dependency injection throughout the project. The problem now is that when I use the usual way of registering the nibs in viewDidLoad()
let cellNib = UINib(nibName: "BatchConsumptionCell", bundle: nil)
tableView.register(cellNib, forCellReuseIdentifier: "BatchConsumptionCell")
and then use them as dequeueReusableCell(withIdentifier: for:) in tableView(tableView: cellForRowAt:)
let batchConsumptionCell = tableView.dequeueReusableCell(withIdentifier: "BatchConsumptionCell", for: indexPath) as! BatchConsumptionCell
batchConsumptionCell.setConsumption(consumption: consumption)
return batchConsumptionCell
I'm not able to inject the dependencies in time.
In the BatchConsumptionCell all I do in tableView(tableView: cellForRowAt:) works fine. This function is called after dequeueReusableCell(withIdentifier: for:) is executed. But as soon as I'm trying to make the tableView(tableView: numberOfRowsInSection:) dynamic I run into problems. This functions seems to be called before dequeueReusableCell(withIdentifier: for:) so the dependencies are not injected at this point.
I tried to override the init(nibName: bundle:) initializer in my BatchConsumptionCell, but this is a UITableViewCell so I was not able to override this.
How do I approach this? Is there any way I could inject the dependencies as the nib and its controller are initialized? Or do I organize my cells all wrong? Any ideas would be much appreciated.
For more clarity here is my code:
ConsumptionDetailViewController
import UIKit
class ConsumptionDetailViewController: UITableViewController {
// MARK: - Properties
var moc: NSManagedObjectContext!
var consumption: Consumption!
// MARK: - Outlet Properties
#IBOutlet weak var labelDate: UILabel!
#IBOutlet weak var labelTime: UILabel!
...
// MARK: - Default Methods
override func viewDidLoad() {
super.viewDidLoad()
let cellNib = UINib(nibName: "BatchConsumptionCell", bundle: nil)
tableView.register(cellNib, forCellReuseIdentifier: "BatchConsumptionCell")
updateTableFields(selectedConsumption: consumption)
}
// MARK: - UI Update Methods
func updateTableFields(selectedConsumption: Consumption) {
labelId.text = selectedConsumption.wtId
...
}
// MARK: - BatchAddEditDelegate Methods
func didFinishEditing(consumption: Consumption) {
updateTableFields(selectedConsumption: consumption)
}
// MARK: - TableView Methods
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
...
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
...
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
...
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
...
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 1 && indexPath.row == 0 {
let batchConsumptionCell = tableView.dequeueReusableCell(withIdentifier: "BatchConsumptionCell", for: indexPath) as! BatchConsumptionCell
batchConsumptionCell.setConsumption(consumption: consumption)
return batchConsumptionCell
}
return super.tableView(tableView, cellForRowAt: indexPath)
}
// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
...
}
}
BatchConsumptionCell
import UIKit
class BatchConsumptionCell: UITableViewCell, UITableViewDataSource, UITableViewDelegate {
var consumption: Consumption!
var batchConsumptionCount: Int!
#IBOutlet weak var tableView: UITableView!
override func awakeFromNib() {
super.awakeFromNib()
var cellNib = UINib(nibName: "BatchConsumptionBasicCell", bundle: nil)
tableView.register(cellNib, forCellReuseIdentifier: "BatchConsumptionBasicCell")
cellNib = UINib(nibName: "BatchConsumptionMultiCell", bundle: nil)
tableView.register(cellNib, forCellReuseIdentifier: "BatchConsumptionMultiCell")
self.tableView.delegate = self
self.tableView.dataSource = self
}
func setConsumption(consumption: Consumption) {
self.consumption = consumption
self.batchConsumptionCount = consumption.batchConsumptions?.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if batchConsumptionCount == 1 { // <-- This does not work
return 3
} else {
return batchConsumptionCount
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if batchConsumptionCount == 1 { // <-- This works fine
let batchConsumptionBasicCell = tableView.dequeueReusableCell(withIdentifier: "BatchConsumptionBasicCell", for: indexPath) as! BatchConsumptionBasicCell
let bc = consumption.batchConsumptions?.allObjects[0] as! BatchConsumption
if indexPath.row == 0 {
batchConsumptionBasicCell.configure(title: "Batch", detail: (bc.batch?.wtId)!)
} else if indexPath.row == 1 {
batchConsumptionBasicCell.configure(title: "Weight", detail: String(describing: bc.weight!))
} else if indexPath.row == 2 {
batchConsumptionBasicCell.configure(title: "Price", detail: String(format:"%.2f", bc.price))
}
} else if batchConsumptionCount >= 2 {
let batchConsumptionMultiCell = tableView.dequeueReusableCell(withIdentifier: "BatchConsumptionMultiCell", for: indexPath) as! BatchConsumptionMultiCell
return batchConsumptionMultiCell
}
return UITableViewCell()
}
}
See the comments // <-- This works fine and
// <-- This does not work in BatchConsumptionCell
You should also register nib to the BatchConsumptionCell class, and implement necessary table view's data source & delegate methods:
class BatchConsumptionCell: UITableViewCell, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var consumption: Consumption!
var batchConsumptionCount: Int!
override func awakeFromNib() {
super.awakeFromNib()
var cellNib = UINib(nibName: "BatchConsumptionBasicCell", bundle: nil)
tableView.register(cellNib, forCellReuseIdentifier: "BatchConsumptionBasicCell")
cellNib = UINib(nibName: "BatchConsumptionMultiCell", bundle: nil)
tableView.register(cellNib, forCellReuseIdentifier: "BatchConsumptionMultiCell")
self.tableView.delegate = self
self.tableView.dataSource = self
}
func setConsumption(consumption: Consumption) {
self.consumption = consumption
self.batchConsumptionCount = consumption.batchConsumptions?.count
tableView.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return consumption == nil ? 0 : 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if batchConsumptionCount == .some(1) { return 3 }
return batchConsumptionCount ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch batchConsumptionCount {
case .some(1):
let batchConsumptionBasicCell = tableView.dequeueReusableCell(withIdentifier: "BatchConsumptionBasicCell", for: indexPath) as! BatchConsumptionBasicCell
let bc = consumption.batchConsumptions?.allObjects[0] as! BatchConsumption
if indexPath.row == 0 {
batchConsumptionBasicCell.configure(title: "Batch", detail: (bc.batch?.wtId)!)
} else if indexPath.row == 1 {
batchConsumptionBasicCell.configure(title: "Weight", detail: String(describing: bc.weight!))
} else if indexPath.row == 2 {
batchConsumptionBasicCell.configure(title: "Price", detail: String(format:"%.2f", bc.price))
}
return batchConsumptionBasicCell
default:
let batchConsumptionMultiCell = tableView.dequeueReusableCell(withIdentifier: "BatchConsumptionMultiCell", for: indexPath) as! BatchConsumptionMultiCell
return batchConsumptionMultiCell
}
}
}

Resources