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

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)
}
}

Related

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.

Add Custom Cell inside Custom Cell

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.

TableViewCell not updating properly swift 2.2

In my app I created two custom tableview cells.
Problem I am facing now the second tableview cell update with last element of the array only.
In cellForRowAtIndexpath array elements are displaying fine.
Consider [ "Value1", "Value2" ] is my array. In tableView only value2 is displaying in two cells.
var title = ["value1","value2"]
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let row = indexPath.row
let x = Id[indexPath.row]
if x == 0{
let cell1 = tableView.dequeueReusableCellWithIdentifier("Cell1", forIndexPath: indexPath) as! MyCell1
return cell1
}
else{
let cell2 = tableView.dequeueReusableCellWithIdentifier("Cell2", forIndexPath: indexPath) as! MyCell2
for index in 0..<myArray.count{
cell2.titleButton.setTitle(title[index],forState:UIControlState.Normal)
}
return cell2
}
}
I am stuck here, your help will be appreciated.
Following is the solution, reason it was going out of range was because value incremented when cell were dequed as cellforrowAtIndexPath was called every time we scrolled down(since some cells were not visible and these cells were dequed when we scrolled down):-
var name = ["HouseBolo","HouseBolo1","HouseBolo2","HouseBolo3"]
var propertyVal:Int = 0
var projectVal:Int = 0
var type = ["Apartment","Villa","Home","Flat","Plot"]
var arrangedData = [String]()
var flatId = [0,1,2,0,0]
override func viewDidLoad() {
super.viewDidLoad()
// I want the Expected Output in Tableview Cell is
// 1. Apartment 2. HouseBolo 3. HouseBolo1 4. Villa 5. Home
for item in flatId {
if item == 0 {
arrangedData.append(type[propertyVal])
propertyVal+=1
}
else {
arrangedData.append(name[projectVal])
projectVal+=1
}
}
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrangedData.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let flatDetails = flatId[indexPath.row]
// For Property Cell
if flatDetails == 0{
let cell = tableView.dequeueReusableCellWithIdentifier("Cell1", forIndexPath: indexPath) as? PropertyCell
if(cell != nil) {
cell!.pType.text = arrangedData[indexPath.row]
}
return cell!
}
// For Project Cell
else {
let cellan = tableView.dequeueReusableCellWithIdentifier("Cell2", forIndexPath: indexPath) as? ProjectCell
if(cellan != nil) {
cellan!.projectName.setTitle(arrangedData[indexPath.row], forState: UIControlState.Normal)
}
return cellan!
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
You need to use :
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! searchCell
in :
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {}
block.
searchCell : is a class of type : UITableViewCell
After that, go in Storyboard and change the identifier of your cell with : "cell"
In the code...
let cell2 = tableView.dequeueReusableCellWithIdentifier("Cell2", forIndexPath: indexPath) as! MyCell2
for index in 0..<myArray.count{
cell2.titleButton.setTitle(title[index],forState:UIControlState.Normal)
}
return cell2
you are iterating over 'myArray' and assigning the value to 'cell2.titleButton'. Cell 2 will always have the last value assigned to it's title. It's assigning it to 'value1', then reassigning it to 'value2'. Looping through the array seems to be the issue (assuming the cells are displaying - just always showing the title from the last item in the array.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
}
You have to add your custom tableview cell class name in the place of UITableViewCell
Something like this -
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> **custom tableview cell class name**
{
}
And also in Storyboard ,change the identifier of your cell with : "cell1" and "cell2"

Bound value in a conditional binding must be of Optional type [IOS - SWIFT]

I am trying to make a TO-DO list app in Xcode by using Swift, and I encounter an error writing one of the function methods on the "if let path = indexPath {" line which says "Bound value in a conditional binding must be of Optional type".
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
if let path = indexPath {
let currentString = dataSource[path.section][path.row]
cell.textLabel?.text = currentString
}
return cell
}
Because indexpath is not optional,you do not need to use conditional binding
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
let currentString = dataSource[indexPath.section][indexPath.row]
cell.textLabel?.text = currentString
return cell
}
why u want use two constant?
fix ure code:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel?.text = dataSource[indexPath.section][indexPath.row]
}
return cell
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel?.text = dataSource[indexPath.section][indexPath.row]
return cell
}
Use this code because I think my previous idea was not good.
You don't need conditional binding here as suggested by Leo.

Returning two cells in cellForRowAtIndexPath using segmented control

I have a segmented control above two UITableViews, one of which is layered above the other. When segmentedControl.selectedSegmentIndex == 1 one of those table views will hide. The problem, however, is that I can't configure the custom cells of the second table view in my one cellForRowAtIndexPath function. I keep getting: Variable 'cell' used before being initialized.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
switch segmentedControl.selectedSegmentIndex {
case 0:
var cell = tableView.dequeueReusableCellWithIdentifier("CellOne", forIndexPath: indexPath) as! CellOne
return cell
case 1:
var cellTwo = tableView.dequeueReusableCellWithIdentifier("CellTwo", forIndexPath: indexPath) as! CellTwo
return cellTwo
default:
var cell: UITableViewCell
return cell
}
}
You have default branch with not initialized cell variable that you returns. I would recommend the change like following:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let result: UITableViewCell
if (segmentedControl.selectedSegmentIndex == 0) {
var cellOne = tableView.dequeueReusableCellWithIdentifier("CellOne", forIndexPath: indexPath) as! CellOne
//Configure here
result = cellOne
} else {
var cellTwo = tableView.dequeueReusableCellWithIdentifier("CellTwo", forIndexPath: indexPath) as! CellTwo
//Configure here
result = cellTwo
}
return result
}

Resources