Refactoring TableView with multiple cell types - swift

Any suggestions regarding factoring a massive view controller, with multiple cell types, cell sizes. Because each cell has its own delegates, the view controller becomes super confusing when navigating through the file.
Or is this the standard approach to for multiple cell types? How would you go about building multiple with multiple sections & cells. Much thanks!
//Rows
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 && sectionArray[0].isExpanded {
return sectionArray.count
} else if section == 0 && sectionArray[0].isExpanded == false {
return sectionArray[0].section.count - 1
}
if section == 1 {
return 3
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 && indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "CreateFavoriteIconCell", for: indexPath) as! CreateFavoriteIconCell
cell.delegate = self
return cell
}
if indexPath.section == 1 {
switch indexPath.row {
case 0:
let cell = tableView.dequeueReusableCell(withIdentifier: "CreateFavoritePhotoCell", for: indexPath) as! CreateFavoritePhotoCell
cell.delegate = self
return cell
case 1:
let cell = tableView.dequeueReusableCell(withIdentifier: "CreateFavoriteLocationCell", for: indexPath) as! CreateFavoriteLocationCell
return cell
case 2:
let cell = tableView.dequeueReusableCell(withIdentifier: "CreateFavoriteDescriptionCell", for: indexPath) as! CreateFavoriteDescriptionCell
return cell
default:
return tableView.cellForRow(at: indexPath)!
}
}
return tableView.cellForRow(at: indexPath)!
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == 0 {
switch indexPath.row {
case 0:
tableView.rowHeight = 58
default:
tableView.rowHeight = 0
}
}
if indexPath.section == 1 {
switch indexPath.row {
case 0:
tableView.rowHeight = 120
case 1:
tableView.rowHeight = 60
case 2:
tableView.rowHeight = 160
default:
tableView.rowHeight = 0
}
}
return tableView.rowHeight
}

Related

Issue while Expanding and Collapse of Table View Cell

i have a button and some content in a cell. Now when i tap a button i want the cell to expand and collapse, which is working fine for cell whose button is tapped. Now issue is coming that when i have expanded one cell and try to expand another cell while keeping first cell expanded it close first the previous cell and than expand my second cell. I want to expand and collapse the cells parallel and can collapse any cell rather than to collapse first. I'm changing height of cell on click of button. This is my code for expanding and collapsing,
extension ActiveConsultantDetailVC : UITableViewDelegate, UITableViewDataSource
{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == 0
{
return 100
}
else if indexPath.row == 1
{
return 80
}
else if indexPath.row == 2
{
if (flag == true && indexPath.row == indexValue)
{
return UITableView.automaticDimension
}
else
{
return 40
}
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
else if indexPath.row == 2
{
let cell = consultantTableView.dequeueReusableCell(withIdentifier: "descriptionCell", for: indexPath) as! ConsultDescriptionTVC
indexDescription = indexPath
cell.expandBtn.addTarget(self, action: #selector(expandDescriptionView), for: .touchUpInside )
cell.selectionStyle = .none
return cell
}
}
#objc func expandDescriptionView()
{
let cell = consultantTableView.cellForRow(at: indexDescription) as! ConsultDescriptionTVC
indexValue = indexDescription.row
if flag && indexValue == indexDescription.row{
//statesDetailTableView.beginUpdates()
self.consultantTableView.reloadRows(at: [indexDescription], with: UITableView.RowAnimation.none)
// statesDetailTableView.endUpdates()
cell.expandBtn.setTitle("-", for: .normal)
flag = false
}
else{
//statesDetailTableView.beginUpdates()
self.consultantTableView.reloadRows(at: [indexDescription], with: UITableView.RowAnimation.none)
// statesDetailTableView.endUpdates()
cell.expandBtn.setTitle("+", for: .normal)
flag = true
}
}
As you can see when i tap it call a function that then expand height of cell. My UI Looks like this,
You just need to create 2 Cells in UITableView(In Storyboard). First cell for those who are not expandable and Second cell for the expandable.(In this case, now you don't need to change the Height of the CELL)
class TableVC: UITableViewController {
// MARK:- Constants And Vars
var isCellNAME1Expanded = false
var isCellNAME2Expanded = false
}
class TableVC: UITableViewDataSource, UITableViewDelegate {
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "simpleCell", for: indexPath) as! SideMenuBasicTableViewCell
switch indexPath.row {
case 0:
cell.itemName.text = "HOME"
break
case 1:
cell.itemName.text = "About Us"
break
case 2:
if(isCellNAME1Expanded){
//expandedCell
let cell = tableView.dequeueReusableCell(withIdentifier: "expandedCell", for: indexPath) as! SideMenuBasicTableViewCell
cell.itemName.text = "Expanded- CEll1"
return cell
}else{
cell.arrowDownImageView.isHidden = false
cell.itemName.text ="Expanded- CEll1"
}
break
case 3:
if(isCellNAME2Expanded){
//expandedCell
let cell = tableView.dequeueReusableCell(withIdentifier: "expandedCell", for: indexPath) as! SideMenuBasicTableViewCell
cell.itemName.text = "Expanded- CEll2"
return cell
}else{
cell.arrowDownImageView.isHidden = false
cell.itemName.text = "Expanded- CEll2"
}
break
case 4:
cell.itemName.text = "Portfolio"
break
case 5:
cell.itemName.text = "Contacts8"
break
default:
break
}
return cell
}
//And in `DidSelectRow` Method
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if(indexPath.row == 2){
if(isCellNAME1Expanded){
isCellNAME1Expanded = false
tableView.reloadRows(at: [indexPath], with: .none)
}else{
isCellNAME1Expanded = true
tableView.reloadRows(at: [indexPath], with: .none)
}
}if(indexPath.row == 3){
if(isCellNAME2Expanded){
isCellNAME2Expanded = false
tableView.reloadRows(at: [indexPath], with: .none)
}else{
isCellNAME2Expanded = true
tableView.reloadRows(at: [indexPath], with: .none)
}
}else if(indexPath.row == 0){
// Handle it yourself
}else if(indexPath.row == 1){
// Handle it yourself
}else if(indexPath.row == 4){
// Handle it yourself
}else if(indexPath.row == 5){
// Handle it yourself
}
}
}

How to divide tableview to sections and give headlines

I have a tableview in my app.
I want to divide my cells into sections and give headlines.
Below I attach the picture (animals, birds headlines):
How do I do that in dynamic prototype cells?
My section data:
var sectionsData = [
"header",
"description",
"diagnoses",
"perscription",
"notes",
"addFaxHeadline",
"addFax",
"addEmailHeadline",
"addEmails",
"givePermissionHeadline",
"select answer"
]
Here is my cell at row function:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print ("indexPath: ", indexPath)
print ("indexPath: ", indexPath[0])
print ("-------")
if (sectionsData[indexPath[0]] == "header") {
let cell = tableView.dequeueReusableCell(withIdentifier: "headerCell", for: indexPath)
return cell
} else if (sectionsData[indexPath[0]] == "description") {
let cell = tableView.dequeueReusableCell(withIdentifier: "headerInfoCell", for: indexPath)
return cell
} else if (sectionsData[indexPath[0]] == "diagnoses") {
let cell = tableView.dequeueReusableCell(withIdentifier: "diagnosisCell", for: indexPath)
return cell
} else if (sectionsData[indexPath[0]] == "perscription") {
let cell = tableView.dequeueReusableCell(withIdentifier: "perscriptionCell", for: indexPath)
return cell
} else if (sectionsData[indexPath[0]] == "notes") {
let cell = tableView.dequeueReusableCell(withIdentifier: "notesCell", for: indexPath)
return cell
} else if (sectionsData[indexPath[0]] == "addFaxHeadline") {
let cell = tableView.dequeueReusableCell(withIdentifier: "addFaxCell", for: indexPath)
return cell
} else if (sectionsData[indexPath[0]] == "addFax") {
let cell = tableView.dequeueReusableCell(withIdentifier: "emailNameCell", for: indexPath)
return cell
} else if (sectionsData[indexPath[0]] == "addEmailHeadline") {
let cell = tableView.dequeueReusableCell(withIdentifier: "addEmailCell", for: indexPath)
return cell
} else if (sectionsData[indexPath[0]] == "addEmails") {
let cell = tableView.dequeueReusableCell(withIdentifier: "emailNameCell", for: indexPath)
return cell
} else if (sectionsData[indexPath[0]] == "givePermissionHeadline") {
let cell = tableView.dequeueReusableCell(withIdentifier: "permisionCell", for: indexPath)
return cell
} else if (sectionsData[indexPath[0]] == "select answer") {
let cell = tableView.dequeueReusableCell(withIdentifier: "selectAnswerCell", for: indexPath)
return cell
}
let cell = tableView.dequeueReusableCell(withIdentifier: "addFaxCell", for: indexPath)
// <<<< ???
return cell
}
and my numbers in row per section function:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if (sectionsData[section] == "header") {
print ("returning 1 ?")
return 1
} else if (sectionsData[section] == "description") {
return 1
} else if (sectionsData[section] == "diagnoses") {
//return visitSummary.diagnoses.count
return 2
} else if (sectionsData[section] == "perscription") {
//return visitSummary.prescriptions.count
return 2
} else if (sectionsData[section] == "notes") {
return 1
} else if (sectionsData[section] == "addFaxHeadline") {
return 1
} else if (sectionsData[section] == "addFax") {
return faxAdded.count
} else if (sectionsData[section] == "addEmailHeadline") {
return 1
} else if (sectionsData[section] == "addEmails") {
return emailsAdded.count
} else if (sectionsData[section] == "givePermissionHeadline") {
return 1
} else if (sectionsData[section] == "select answer") {
return 1
} else {
return 0
}
return 0
}
and my number of sections:
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
print ("sectionsData.count: ", sectionsData.count)
return sectionsData.count
}
All of the tutorials I find is for one section and I have a very amount of sections to show.
How would I divide it and give them headlines?
Let's clean up your code first:
enum Section: Int, CaseIterable {
case header = 0, description, diagnoses, prescription, notes, addFaxHeadline, addFax, addEmailHeadline, addEmails, givePermissionHeadline, selectAnswer
}
var sectionData: [Section] = [
.header,
.description,
.diagnoses
...
]
override func numberOfSections(in tableView: UITableView) -> Int {
return sectionsData.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection sectionIndex: Int) -> Int {
let section = sectionData[sectionIndex]
switch section {
case .header:
return 1
case .description:
return 1
// ...
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let section = sectionData[sectionIndex]
switch section {
case .header:
let cell = tableView.dequeueReusableCell(withIdentifier: "headerCell", for: indexPath)
return cell
// ... etc
}
}
Now, we can return section title just using a String:
override func tableView(_ tableView: UITableView, titleForHeaderInSection sectionIndex: Int) -> String? {
let section = sectionData[sectionIndex]
switch section {
case .header:
return "Header title"
case .description:
return "Description title"
default:
return nil
}
}
Another option is to use tableView(:viewForHeaderInSection:) and tableView(:heightForHeaderInSection:):
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 44
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = UIView()
let label = UILabel()
view.addSubview(label)
// setup constraints accordingly
// setup title of the label
return view
}
You can also use a custom reusable header which would be registered and dequeued in the same way cells are dequeued.
var sectionsData = [
"header",
"description",
"diagnoses",
"prescription",
"notes",
"addFaxHeadline",
"addFax",
"addEmailHeadline",
"addEmails",
"givePermissionHeadline",
"select answer"
] // Your Array
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? //*Data Source method for header title*
{
// Safe cast
if let sectionArray = sectionsData as? [String]
{
return sectionArray[section]
}
// A fail safe
return "No Header"
}
Now I see. You are misunderstanding how these methods work. They are called for every cell in every section.
So, if you return 4 in numberOfSections, the method numberOfRowsInSection will be called 4 times, and sectionIndex (now called section in latest versions) will have the current section (0 to 3 in our example).
Therefore, if you want to call the second section "Birds" and let all the others nil, your code will look like this:
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 1 {
return "Birds"
}
// Otherwise
return nil
}
Same thing for how many rows each section will have:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
// 1 row for the first section
return 1
} else if section == 1 {
// 3 rows for the second section
return 3
}
// 2 rows for every other section
return 2
}
And, finally, what cell will be used in each indexPath:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Figure out which row and section you are talking about
let row = indexPath.row
let section = indexPath.section
// Now you know where you are in the TableView, create the corresponding cell according to your project
// Start by dequeueing a custom cell using the identifier and forcing the cell to become your custom cell
let cell = tableView.dequeueReusableCell(withIdentifier: customCellID) as! CustomTableViewCell
// Do aditional setup to this cell
cell.textLabel?.text = "This is cell \(row) in section \(section)"
// Return the cell when you are ready
return cell
}
Remember Sulthan's suggestion to create an enum for your sections.

Show / Hide Sections in table view based on selection

i developing ipad application, this application for assets requests,
i have 6 checkboxes and table view like the image
i created 6 sections in table, i need when user select for ex laptop in table view only laptop section will appear and other sections will removed or hide.
this is my code
#objc func circleBoxValueChanged(sender: Checkbox) {
tblView.isHidden = false
switch sender.tag {
case 1:
print("1")
case 2:
print("2")
case 3:
print("3")
case 4:
print("4")
case 5:
print("5")
case 6:
print("6")
default:
break
}
print("circle box value change: \(sender.isChecked)")
}
// MARK: - TableView Delegate
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 200
}
func numberOfSections(in tableView: UITableView) -> Int {
return 6
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 0 {
return "Laptop"
}else if section == 1 {
return "Mobile"
}else if section == 2 {
return "Ex Badge"
}
else if section == 3 {
return "VIP Badge"
}
else if section == 4 {
return "Gift"
}
else if section == 5{
return "Locker"
}else{
return "Other"
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return 1
}else if section == 1{
return 1
}else if section == 2{
return 1
}else if section == 3{
return 1
}else if section == 4{
return 1
}else if section == 5{
return 1
}else{
return 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
switch indexPath.section {
case 0:
let cell1 = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! laptop_MobileTableViewCell
return cell1
case 1:
let cell1 = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! laptop_MobileTableViewCell
return cell1
case 2:
let cell1 = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as! OtherRequstTableViewCell
return cell1
case 3:
let cell1 = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as! OtherRequstTableViewCell
return cell1
case 4:
let cell1 = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as! OtherRequstTableViewCell
return cell1
case 5:
let cell1 = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as! OtherRequstTableViewCell
return cell1
default:
let cell1 = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as! OtherRequstTableViewCell
return cell1
}
}
can you help me
You can try
struct Item {
var name:String
var isShown:Bool
}
let arr = [Item(name:"LapTop",isShown:true)] // and so--on
in numberOfSections
return arr.filter {$0.isShown}.count
in titleForHeader
return arr.filter{$0.isShown}[indexPath.section].name

Sections in UITableView with Custom Cells

I have the following code thus far.
var someData = [SomeData]()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! Cell1
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as? Cell2
let someData = [indexPath.row]
//Set up labels etc.
return cell!
}
}
I need Cell1 which is a static cell and will always remain at indexPath 0 to be in a section called "Section1" for example & all of the Cell2's to be in a section called "Section2"
Other DataSource & Delegate Methods;
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return 1
} else {
return someData.count
}
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 0 {
return "Section1" }
else {
return "Section2"
}
}
This returns me everything I need for the first section, however, when it comes to the second section (because of the code inside cellForRowAtIndex somewhere) section 2 contains Cell2 at indexPath 0.
Any help greatly appreciated.
Root cause:
In cellForRowAtIndexPath check for indexPath.section instead of indexPath.row
Fix:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! Cell1
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as? Cell2
let someData = [indexPath.row]
//Set up labels etc.
return cell!
}
}

TableView With 3 Sections and cells crashing

I have a simple UITableViewController with 3 sections and each section has 3 rows. I have already allocated each cell it's reuse identifier.
When I run the code, I get an EXE_BAD_INSTRUCTION error at return cell.
Here is my code:
import UIKit
class settingsViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 3
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 3
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell : UITableViewCell!
if indexPath.section == 1
{
if indexPath.row == 1
{
cell = tableView.dequeueReusableCellWithIdentifier("draftCell", forIndexPath: indexPath) as UITableViewCell
}
else if indexPath.row == 0
{
cell = tableView.dequeueReusableCellWithIdentifier("profileCell", forIndexPath: indexPath) as UITableViewCell
}
else if indexPath.row == 2
{
cell = tableView.dequeueReusableCellWithIdentifier("logoutCell", forIndexPath: indexPath) as UITableViewCell
}
}
else if indexPath.section == 2{
if indexPath.row == 0
{
cell = tableView.dequeueReusableCellWithIdentifier("facebookCell", forIndexPath: indexPath) as UITableViewCell
}
else if indexPath.row == 1
{
cell = tableView.dequeueReusableCellWithIdentifier("twitterCell", forIndexPath: indexPath) as UITableViewCell
}
else if indexPath.row == 2
{
cell = tableView.dequeueReusableCellWithIdentifier("rateusCell", forIndexPath: indexPath) as UITableViewCell
}
}
else if indexPath.section == 3
{
if indexPath.row == 0
{
cell = tableView.dequeueReusableCellWithIdentifier("creditsCell", forIndexPath: indexPath) as UITableViewCell
}
else if indexPath.row == 1
{
cell = tableView.dequeueReusableCellWithIdentifier("contactusCell", forIndexPath: indexPath) as UITableViewCell
}
else if indexPath.row == 2
{
cell = tableView.dequeueReusableCellWithIdentifier("termsandconditionsCell", forIndexPath: indexPath) as UITableViewCell
}
}
return cell
}
For section number 0 you haven't written cellForRowAtIndexPath. You have given number of sections = 3, so its index starts from 0,
Correct your indexpath.section comparison i.e do it for indexpath.section == 0, indexpath.section == 1 and indexpath.section == 2.
Also you haven't registered class for tableview cell like
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
You would be better off using a static tableView in storyboard, instead of trying to programmatically code static cells in an dynamic tableView.
Apple's Table View Programming Guide recommends:
Use static cells to design a table with a fixed number of rows, each with its own layout. Use static cells when you know what the table looks like at design time, regardless of the specific information it displays.
If you are determined to dynamically handle this, your code would be easier to read and maintain if you used a switch statement, instead of nested ifs.
You have 3 sections but the index should start from 0 (0,1,2,3,...). So modify your code starting from indexPath.section == 0 (which is the first section of your table). Furthermore I agree with PetahChristian that you may use static cell to design your table.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell : UITableViewCell!
if indexPath.section == 0
{
if indexPath.row == 1
{
cell = tableView.dequeueReusableCellWithIdentifier("draftCell", forIndexPath: indexPath) as UITableViewCell
}
else if indexPath.row == 0
{
cell = tableView.dequeueReusableCellWithIdentifier("profileCell", forIndexPath: indexPath) as UITableViewCell
}
else if indexPath.row == 2
{
cell = tableView.dequeueReusableCellWithIdentifier("logoutCell", forIndexPath: indexPath) as UITableViewCell
}
}
else if indexPath.section == 1{
if indexPath.row == 0
{
cell = tableView.dequeueReusableCellWithIdentifier("facebookCell", forIndexPath: indexPath) as UITableViewCell
}
else if indexPath.row == 1
{
cell = tableView.dequeueReusableCellWithIdentifier("twitterCell", forIndexPath: indexPath) as UITableViewCell
}
else if indexPath.row == 2
{
cell = tableView.dequeueReusableCellWithIdentifier("rateusCell", forIndexPath: indexPath) as UITableViewCell
}
}
else if indexPath.section == 2
{
if indexPath.row == 0
{
cell = tableView.dequeueReusableCellWithIdentifier("creditsCell", forIndexPath: indexPath) as UITableViewCell
}
else if indexPath.row == 1
{
cell = tableView.dequeueReusableCellWithIdentifier("contactusCell", forIndexPath: indexPath) as UITableViewCell
}
else if indexPath.row == 2
{
cell = tableView.dequeueReusableCellWithIdentifier("termsandconditionsCell", forIndexPath: indexPath) as UITableViewCell
}
}
return cell
}