How to add two custom cell into tableview in storyboard in Swift? - swift

I have a tableView with two different custom cell. One cell have a switch and other a image, I have Two separated custom class for the cells, identifiers.. but I can't see this. i don't know if I need change the configuration in story board to dynamic or other thing.. Can I show two different custom cells
Thanks!

Check the criteria for showing each specific custom cell, then cast to that cell as needed:
override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell? {
if (criteria for cell 1) {
let cell = tableView!.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as? Cell1
return (cell)
}
else {
let cell = tableView!.dequeueReusableCellWithIdentifier("cell2", forIndexPath: indexPath) as? Cell2
return (cell)
}
}
Swift 3
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath -> UITableViewCell {
if (criteria for cell 1) {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! Cell1
return cell
}
else {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as! Cell2
return cell
}
}

override func tableView(tableView: UITableView?,cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell? {
if (...) {
let cell : Mycell1 = tableView!.dequeueReusableCellWithIdentifier("Mycell1", forIndexPath: indexPath) as? Mycell1
return cell
}
else {
let cell : Mycell2 = tableView!.dequeueReusableCellWithIdentifier("Mycell2", forIndexPath: indexPath) as? Mycell2
return cell
}
}

Related

Display three reusbale cells in tableview - Swift 5

I have 3 UITableViewCell with XIB files but on my tableview I can't display my three UITableViewCell, only can load the first two
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if (indexPath.item % 2 == 0) {
let cell = tableView.dequeueReusableCell(withIdentifier: "CaptureNameTableViewCell", for: indexPath) as! CaptureNameTableViewCell
cell.nameTextField.text = ""
cell.nameTextField.tag = indexPath.row
cell.nameTextField.delegate = self
return cell
} else if indexPath.section == 2 {
let cell = tableView.dequeueReusableCell(withIdentifier: "CapturePhotoTableViewCell", for: indexPath) as! CapturePhotoTableViewCell
cell.displayImage = imageView
cell.cellDelegate = self
cell.selectImage.tag = indexPath.row
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "PieChartTableViewCell", for: indexPath) as! PieChartTableViewCell
return cell
}
}
You need to register the xib tableViewCells inside of the tableViewController:
First create an id property inside of the cells xib class, to use as the cell’s reuse identifier (make the name of this the same as your reuse identifier for the cell which you set in the xib file):
let id = "cellIdentifier" // Name this appropriately
Then create a nib method inside of the cell's xib class:
func nib() -> UINib {
return UINib(named: "cellIdentifier", bundle: nil)
}
Then inside of a lifecycle method such as viewDidLoad():
tableView.register(nib: cell.nib, forCellReuseIdentifier: cell.id)
Finally, specify which cells you want to be where in the table view at which indexPath.row. (Which row in the table view):
switch indexPath.row {
case 0: // First cell
let cell = tableView.dequeueReusableCell(withIdentifier: "CaptureNameTableViewCell", for: indexPath) as! CaptureNameTableViewCell
// Configure cell as before
return cell
case 1: // Second cell
let cell = tableView.dequeueReusableCell(withIdentifier: "CapturePhotoTableViewCell", for: indexPath) as! CapturePhotoTableViewCell
// Configure cell as before
return cell
case 2: // Third cell
let cell = tableView.dequeueReusableCell(withIdentifier: "PieChartTableViewCell", for: indexPath) as! PieChartTableViewCell
// Configure cell as before
return cell
default:
return UITableViewCell() // This should not be reached but a switch statement must cover all possibilities.
}

How to switch custom xib cell when didSelect call?

I have a tableView with 2 custom xib cells. I want to switch the custom cell when user tapped it also adjust the cell height. How do I achieve it? I tried to use container view but then the height would be the same. I want to know if it is possible to do it with two xib for tableView cell? Thank you.
var isContactView: Bool = true
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
tableView.register(UINib(nibName: "ContactTableViewCell", bundle: nil), forCellReuseIdentifier: "contactCell")
tableView.register(UINib(nibName: "DetailTableViewCell", bundle: nil), forCellReuseIdentifier: "detailCell")
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
//if ContactTableViewCell return 40
//if DetailTableViewCell return 150
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//by default the cell view is ContactTableViewCell.
//When user tapped the cell it will change to DetailTableViewCell.
if isContactView {
let cell = tableView.dequeueReusableCell(withIdentifier: "contactCell", for: indexPath) as! ContactTableViewCell
//do something...
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "detailCell", for: indexPath) as! DetailTableViewCell
//do something...
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//not sure how to change the xib in here.
//if cell view is ContactTableViewCell
cell view = tableView.dequeueReusableCell(withIdentifier: "detailCell", for: indexPath) as! DetailTableViewCell
isContactView = false
tableView.reloadData()
//else
cell view = tableView.dequeueReusableCell(withIdentifier: "contactCell", for: indexPath) as! ContactTableViewCell
isContactView = true
tableView.reloadData()
}
There are 2 cases:
If there's just single cell to be viewed, then just put the following code in didSelect:
isContactView = !isContactView
tableView.reloadData()
If there are multiple cells in which the condition is to be applied. Please put a key in your data model.
For example:
testArr is the array of objects that you are displaying in tableview. Then keep a key, say isContactView in this model. And put the login based upon this key.
Like in case of cellForRow:
if testArr[indexpath.row].isContactView {
let cell = tableView.dequeueReusableCell(withIdentifier: "contactCell", for: indexPath) as! ContactTableViewCell
//do something...
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "detailCell", for: indexPath) as! DetailTableViewCell
//do something...
}
And in didselect:
isContactView = !testArr[indexPath.row].isContactView

Crash: Attempted to dequeue multiple cells for the same index path, which is not allowed

I have tableview datasource func to build a cell from a factory method function.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return OWTableViewOrganizer.instance.configureCell(at: indexPath)!
}
The factory method is here:
func configureCell(at indexPath: IndexPath) -> UITableViewCell? {
var cell = UITableViewCell()
switch indexPath.section {
case thisWorkoutSections.barbel.sectionNumber():
cell = barebellCell(indexPath: indexPath)
break
case thisWorkoutSections.lastWorkout.sectionNumber():
cell = lastWorkoutCell(indexPath: indexPath)
break
case thisWorkoutSections.personalRecord.sectionNumber():
cell = personalRecordCell(indexPath: indexPath)
break
case thisWorkoutSections.notes.sectionNumber():
break
default:
break
}
return cell
}
I have this code to build the cell:
func lastWorkoutCell(indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: WorkoutSetTableViewCell.cellIdentifier(), for: indexPath) as! WorkoutSetTableViewCell
if OWTableViewOrganizer.instance.lastWorkoutExerciseSets.count > 0 {
if indexPath.row < OWTableViewOrganizer.instance.lastWorkoutExerciseSets.count {
let logExerciseSet = OWTableViewOrganizer.instance.lastWorkoutExerciseSets[indexPath.row]
let setNumber = indexPath.row + 1
if let weight = logExerciseSet.weight?.doubleValue, let reps = logExerciseSet.reps?.intValue {
cell.setupCellWithData(setNumber: setNumber, weight: weight, reps: reps)
}
} else {
cell.setupCellWithData(setNumber: -1, weight: 0, reps: 0)
}
} else {
cell.setupCellWithData(setNumber: -1, weight: 0, reps: 0)
}
return cell
}
But time to time this line crashes for me:
let cell = tableView.dequeueReusableCell(withIdentifier: WorkoutSetTableViewCell.cellIdentifier(), for: indexPath) as! WorkoutSetTableViewCell
With error:
Attempted to dequeue multiple cells for the same index path, which is not allowed. If you really need to dequeue more cells than the table view is requesting, use the -dequeueReusableCellWithIdentifier: method (without an index path)
I know code style and design is not ideal here, please skip this if you have comments.
I don't know where to look, I tried simply remove indexPath, but it looks does not help or bring even more issues:
let cell = tableView.dequeueReusableCell(withIdentifier: WorkoutSetTableViewCell.cellIdentifier()) as! WorkoutSetTableViewCell
I have one controller which presents another one at the top of it (like in Apple music) and I can swipe down to show bottom controller and swipe up to bring back top controller. I noticed in log that I have some presentation alert, not sure if this something I need to deal with to resolve the issue above but JFY info.
It seems like there are two table view trigger
tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
and you only dequeue cell from 1 table view at
let cell = tableView.dequeueReusableCell(withIdentifier: WorkoutSetTableViewCell.cellIdentifier(), for: indexPath) as! WorkoutSetTableViewCell
You should try to pass tableView from
tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
to
lastWorkoutCell(indexPath: IndexPath)
(which will become lastWorkoutCell(indexPath: IndexPath, tableView: UITableView)) and dequeue cell from tableView

Two Table Views in One VC

I want to display two (or more) table views from a single view controller. I mean display simultaneously, e.g., beside each other or one above the other. The only way I can think of doing it is with child view controllers. Is there a better or easier way?
Thanks for your comments.
Yes of course you can use like this:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
if tableView == firstTableView
{
let cell = tableView.dequeueReusableCell(withIdentifier: "LabelCell1", for: indexPath)
cell.textLabel?.text = "Section \(indexPath.section) Row \(indexPath.row)"
return cell
}
else if (tableView == secondTableView)
{
let cell = tableView.dequeueReusableCell(withIdentifier: "LabelCell2", for: indexPath)
cell.textLabel?.text = "Section \(indexPath.section) Row \(indexPath.row)"
return cell
}
else
{
return UITableViewCell()
}
}
Similar to other tableview delegate methods, you should add a condition for each table
If your use case is to have two individually scrolling table views then you can simply add two table views in the xib, assign datasource and delegates and call it a day.
If your use case is to display two types of information on a page I'd recommend using just one table view and handling what to display manually.
Let me know if you need any more help.
Use Switch Condition
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
switch tableView {
case firsttableView:
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell
cell.label1.text = "Zaid"
cell.label2.text = "Ahamd"
return cell
case secondTableView:
let cell = tableView.dequeueReusableCell(withIdentifier: "SecondTableViewCell", for: indexPath) as! SecondTableViewCell
cell.labelText.text = "ZaidAfzalMughal"
return cell
default:
print("Something wrong")
}
return cell
}

Tableview cells lines disappear

Does anyone have an official answer as to why some tableview cell lines disappear on scroll? Is this a glitch? I've seen some answers on how to remove them but what is causing this problem to begin with?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "DisplayHeader") as! DisplayTVC
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "PictureDisplay") as! PictureTVC
cell.collectionView.reloadData()
return cell
}
}