Add Custom Cell inside Custom Cell - ios

I have an interesting problem. as i am new to Swift.
I have created on TableView and added CUSTOM CELL using Storyboard. Now i want add another CUSTOM CELL When click on first CUSTOM CELL UIButton.
Second Custom Cell is created using XIB. now when i register That second Cell in didload then i see blank tableview as Second custom cell is Blank.
i have used following Code:
for registering Second cell
self.tableView.registerNib(UINib(nibName: "customCell", bundle: nil), forCellReuseIdentifier: "customCell")
and cell for row at index
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! Cell
cell.nameLbl.text = "Hello hello Hello"
let Customcell = tableView.dequeueReusableCellWithIdentifier("customCell", forIndexPath: indexPath) as! customCell
if self.Selected == "YES" {
if self.selectedValue == indexPath.row {
return Customcell
}
return cell
}
else{
return cell
}
}
Here Cell object is for Storyboard Cell and Customcell is for XIB Second custom cell.
please suggest me how to do that.

First ensure your ViewController is the UITableViewDelegate and UITableViewDataSource of the tableView, and that you have an outlet for the tableView
Next you need to register the custom cell in the viewDidLoad method:
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "customCell")
}
It is easiest to save an array of cells that have been selected if you are going to have more than 1 cell that you want to modify when pressed. This can be a variable within the ViewController:
var customCellIndexPaths: [IndexPath] = []
when a cell is selected you can simply add it to the array of custom cell IndexPaths (if it is not already a custom cell), and then reload that cell:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if customCellIndexPaths.contains(indexPath) == false {
customCellIndexPaths.append(indexPath)
tableView.reloadRows(at: [indexPath], with: .automatic)
}
}
In the cellForRowAt method we must check whether the cell has been selected and if so return the custom cell, else return a normal cell:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if customCellIndexPaths.contains(indexPath) {
return tableView.dequeueReusableCell(withIdentifier: "customCell")!
}
let cell = UITableViewCell(style: .default, reuseIdentifier: "normalCell")
cell.textLabel?.text = "Regular Cell"
return cell
}
There you have it. Now you should receive a smooth animation of a normal cell becoming a CustomCell when being selected.

Related

How do you initialize/use UITableViewCells with CellStyle = .value1 programmatically?

I want to use Apple's given Cell Style value1 for my cells and I am not sure how this is done correctly. The only possible way to set the cell style is during the Cell's initialization, but I don't think subclassing should be necessary in this case.
What would be the correct way to set the CellType?
I tried to get it done in tableView(_:cellForRowAt:), but dequeueReusableCell(withIdentifier:for:) does not return an Optional, which is why my logic cannot work.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCellIdentifier", for: indexPath)
if cell == nil {
cell = UITableViewCell.init(style: .value1, reuseIdentifier: "myCellIdentifier")
}
// setup cell text and so on
// ...
return cell
}
Don't call tableView.register(...)
Instead, use this approach in cellForRowAt:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// try to dequeue a cell
var cv1 = tableView.dequeueReusableCell(withIdentifier: "cv1")
// if that fails, create a new one
if cv1 == nil {
cv1 = UITableViewCell(style: UITableViewCell.CellStyle.value1, reuseIdentifier: "cv1")
}
// just for sanity
guard let cell = cv1 else { fatalError("Failed to get a cell!") }
// set the cell properties as desired
cell.contentView.backgroundColor = .yellow
cell.detailTextLabel?.text = "Row \(indexPath.row)"
return cell
}

cellForRow(at: ) returns nil

So I have this function.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as! customCell
changeCellProperty(selectedIndexPath: indexPath)
return cell;
}
func changeCellProperty(selectedIndexPath: IndexPath){
print("indexpath = \(selectedIndexPath)") . // printing [0,0] and all values
let cell = self.tableView.cellForRow(at: selectedIndexPath) as! customCell
// got nil while unwrapping error in above statement.
cell.label.text = ""
// and change other properties of cell.
}
I am not able to understand the error.
When I am getting the indexpath, then why I am not able to point a particular cell and change properties accordingly.
You cannot access a cell that has not yet been added to the tableView. That is what you are trying to do here in changeCellProperty method. So, if your dequeue works, then all you would need to do is pass the dequeued cell to that method.
func changeCellProperty(cell: customCell){
cell.label.text = ""
// and change other properties of cell.
}
Your cellForRowAt method would look like this.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as! customCell
changeCellProperty(cell: cell)
return cell
}
Note: class names should be UpperCamelCase. So your customCell should be named CustomCell.

Custom UITableViewCell created from .xib doesn't show

I'm lost. I searched and searched and cannot find the reason why my custom cell isn't displayed.
// ProfileCell.swift:
import UIKit
import QuartzCore
class ProfileCell: UITableViewCell {
#IBOutlet weak var profileNameLabel: UILabel!
#IBOutlet weak var profilePictureView: UIImageView!
}
The second default TableViewCell is displayed normally. I have no missing constraints in Interface Builder or any Errors. ProfileCell is selected in the ProfileCell.xib identity tab as the custom class.
// MoreTableViewControllerIB.swift
import UIKit
class MoreTableViewControllerIB: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// this cell is missing
if indexPath.row == 0 {
tableView.register(UINib(nibName: "ProfileCell", bundle: nil), forCellReuseIdentifier: "ProfileCell")
let cell = tableView.dequeueReusableCell(withIdentifier: "ProfileCell", for: indexPath) as! ProfileCell
cell.profileCommentLabel.text = "Test Comment Label"
cell.profilePictureView.image = UIImage(named:"profile_picture_test")
return cell
// this cell is displayed perfectly
}else if indexPath.row == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "statisticsCell") ?? UITableViewCell(style: .default, reuseIdentifier: "statisticsCell")
cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator
cell.textLabel?.text = "Statistics"
cell.imageView.image = UIImage(named:"statistics")
return cell
// has to return a cell in every scenario
}else{
let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell
return cell
}
}
}
Here is a screenshot of what I get.
tableView.register(UINib(nibName: "ProfileCell", bundle: nil), forCellReuseIdentifier: "ProfileCell")
add this line in viewDidLoad or viewWillApppear
So I found out what my mistake was. Pretty stupid and it cost me half a day:
The cell was already displayed, but the default height wasn't big enough to see it. I thought the set height in the .xib would be used. It apparently is not.
So I added this:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == 0 {
return 192 // the height for custom cell 0
}
}
In my case I had to additionally register nib with view of my cell:
myTableView.register(UINib(nibName: "nibwithcell", bundle: nil), forCellReuseIdentifier: "cell") // you need to register xib file

Insert custom UITableViewCell on button click

I've been trying and researching for the whole day and still not able to find the right answer.
I have a button and I want to insert customized UITableViewCell in my static UITableView upon button click.
Here's what I have done. I created an xib file with my customized UITableViewCell and have assigned swift file to it.
In the viewdidload of my tableviewcontroller, I registered my UITableViewCell:
override public func viewDidLoad() {
super.viewDidLoad()
let nib = UINib(nibName: "TableViewCell", bundle: nil)
addContactTableView.registerNib(nib, forCellReuseIdentifier: "cell")
}
Here's my function for my button click:
#IBAction func buttonClick(sender: AnyObject) {
if let button = sender as? UIButton {
if let superview = button.superview {
if let cell = superview.superview as? UITableViewCell {
indexPath_g = self.tableView.indexPathForCell(cell)!
}
}
}
print(indexPath_g.row)
addContactTableView.beginUpdates()
addContactTableView.insertRowsAtIndexPaths([
NSIndexPath(forRow: indexPath_g.row, inSection: 1)
], withRowAnimation: .Automatic)
addContactTableView.endUpdates()
}
And my cellForRowAtIndexPath:
public override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath_g) as! TableViewCell
if(indexPath.section == 1) {
//Configure the cell...
cell.detail_field.placeholder = "Phone"
}
return cell
}
I tried to run this and I keep getting this error:
fatal error: unexpectedly found nil while unwrapping an Optional value
Insert the UITableviewCell in button action. When tapping on button, you can get the indexPath of the cell and insert anywhere in the UItableview.Just add two methods [tableView beginUpdate] and [tableView endUpdate] after inserting the cell using insertRowsAtIndexPaths method.
My first guess is your cellForRow method:
public override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath_g) as! TableViewCell
...
}
change indexPath_g to indexPath

What should I write in tableView(_:cellForRowAtIndexPath:) method to custom cells?

I'm designing a tableview with 3 custom cells.
I want to customize them by adding unique accessory Type.
I've crated a tableViewController with static cells. Each cell I wrote a special Identifier and special class.
How should my tableView fund looks like for 3 custom cells?
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let CityCellIdentifier = "CityTableViewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(CityCellIdentifier, forIndexPath: indexPath) as! CityTableViewCell
// Configure the cell...
return cell
}
should I create three cell variables for that?
Per my answer here, use your own variation of the following code:
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)
}
}

Resources