I have made a drop down gender which is working fine however I have another drop down on same viewcontroller which shows drop down but when I select the item it gives error fatal error: unexpectedly found nil while unwrapping an Optional value I have tried out but confused. help me to solve the bloodList dropdown.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var genderButton: UIButton!
#IBAction func genderButton(_ sender: Any) {
self.PressDrop()
view.addSubview(genderTable)
}
#IBOutlet weak var genderTable: UITableView!
var flag = 1
var dropDownList = [String]()
#IBOutlet weak var bloodButton: UIButton!
var bloodList = [String]()
#IBAction func bloodButton(_ sender: Any) {
self.PressBlood()
view.addSubview(bloodTable)
}
#IBOutlet weak var bloodTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
dropDownList = ["Male", "Female", "Other"]
genderTable.delegate = self
genderTable.dataSource = self
genderTable.isHidden = true
view.addSubview(genderTable)
genderTable.layer.cornerRadius = 10
bloodList = ["A+", "A-", "AB+", "AB-"]
bloodTable.delegate = self
bloodTable.dataSource = self
bloodTable.isHidden = true
view.addSubview(bloodTable)
bloodTable.layer.cornerRadius = 10
}
func PressDrop() {
if flag == 0 {
UIView.setAnimationDuration(0.5)
self.genderTable.isHidden = true
self.flag = 1
}
else{
UIView.setAnimationDuration(0.5)
self.genderTable.isHidden = false
self.flag = 0
}
}
func PressBlood() {
if flag == 0 {
UIView.setAnimationDuration(0.5)
self.bloodTable.isHidden = true
self.flag = 1
}
else{
UIView.setAnimationDuration(0.5)
self.bloodTable.isHidden = false
self.flag = 0
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dropDownList.count
}
func tableViewBlood(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return bloodList.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = genderTable.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel!.text = dropDownList[indexPath.row]
return cell
}
func tableViewTwo(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = bloodTable.dequeueReusableCell(withIdentifier: "bloodCell", for: indexPath)
cell.textLabel!.text = bloodList[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedData = dropDownList[indexPath.row]
genderButton.setTitle(selectedData, for: .normal)
self.genderTable.isHidden = true
self.flag =
let indexPath = genderTable.indexPathForSelectedRow
let currentCell = genderTable.cellForRow(at: indexPath!)! as UITableViewCell
let finalresult = currentCell.textLabel!.text!
print("\(finalresult)")
}
private func tableViewTwo(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedBlood = bloodList[indexPath.row]
bloodButton.setTitle(selectedBlood, for: .normal)
self.bloodTable.isHidden = true
self.flag = 1
let indexPathTwo = bloodTable.indexPathForSelectedRow
let currentCellBlood = bloodTable.cellForRow(at: indexPathTwo!)! as UITableViewCell
let finalresultBlood = currentCellBlood.textLabel!.text!
print("\(finalresultBlood)")
}
}
You cannot change default delegate methods of your tableView, give conditions in the delegate methods like below :
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == genderTable {
return dropDownList.count
}
return bloodList.count
}
Also make similar changes in the remaining delegate methods.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == genderTable {
let cell = genderTable.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel!.text = dropDownList[indexPath.row]
return cell
} else {
let cell = bloodTable.dequeueReusableCell(withIdentifier: "bloodCell", for: indexPath)
cell.textLabel!.text = bloodList[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView == genderTable {
let selectedData = dropDownList[indexPath.row]
genderButton.setTitle(selectedData, for: .normal)
self.genderTable.isHidden = true
let currentCell = genderTable.cellForRow(at: indexPath)! as UITableViewCell
let finalresult = currentCell.textLabel!.text!
print("\(finalresult)")
} else {
let selectedBlood = bloodList[indexPath.row]
bloodButton.setTitle(selectedBlood, for: .normal)
self.bloodTable.isHidden = true
let currentCellBlood = bloodTable.cellForRow(at: indexPath)! as UITableViewCell
let finalresultBlood = currentCellBlood.textLabel!.text!
print("\(finalresultBlood)")
}
}
Don't create like this
func tableViewTwo(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell (This will consider as new method to your current class)
They are all in build delegate methods of UITableview, you should override it, you cannot change it.
Instead of creating method, you try with Bool variable in respective button action.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
If isDrop == true{
return dropDownList.count
}else{
return bloodList.count
}
}
Like change the condition
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
I waited for an answer but did not find :( that's ok . I thought a number of times and then come to this code yahoooo!!! then i believed i am really a programmer. Actually i did not defined the condition for each table view so i was in nightmare. This code is pure programatically and does not require any irritating third party library or awkward pods
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == tableViewB {
return dropDownList.count
}
else {
return genderL.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == tableViewB {
let cell = tableViewB.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel!.text = dropDownList[indexPath.row]
return cell
}
else {
let cell = genderT.dequeueReusableCell(withIdentifier: "gender", for: indexPath)
cell.textLabel!.text = genderL[indexPath.row]
return cell
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView == tableViewB {
let selectedData = dropDownList[indexPath.row]
buttonB.setTitle(selectedData, for: .normal)
self.tableViewB.isHidden = true
self.flag = 1
let indexPath = tableViewB.indexPathForSelectedRow
let currentCell = tableViewB.cellForRow(at: indexPath!)! as UITableViewCell
let finalresult = currentCell.textLabel!.text!
print("\(finalresult)")
}
else {
let selectedDataG = genderL[indexPath.row]
genderB.setTitle(selectedDataG, for: .normal)
self.genderT.isHidden = true
self.flag = 1
let indexPath = genderT.indexPathForSelectedRow
let currentCell = genderT.cellForRow(at: indexPath!)! as UITableViewCell
let finalresult = currentCell.textLabel!.text!
print("\(finalresult)")
}
}
Related
I have attached the image click the card view expands the same card inside the table cell dynamically its passible to achieve this?
I have searched a lot but not working
Hear my code added header cell with CardView
added arrow button to click the button expand the cell
its able expand but not in parent card it was showing diff card
I have adde my source code
var hiddenSections = Set<Int>()
let tableViewData = [
["1","2","3","4","5"],
["1","2","3","4","5"],
["1","2","3","4","5"],
]
override func viewDidLoad() {
super.viewDidLoad()
let CustomeHeaderNib = UINib(nibName: "CustomSectionHeader", bundle: Bundle.main)
historyTableView.register(CustomeHeaderNib, forHeaderFooterViewReuseIdentifier: "customSectionHeader")
}
func numberOfSections(in tableView: UITableView) -> Int {
return self.tableViewData.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.hiddenSections.contains(section) {
return 0
}
return self.tableViewData[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = self.tableViewData[indexPath.section][indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return view.frame.width/4
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = self.historyTableView.dequeueReusableHeaderFooterView(withIdentifier: "customSectionHeader") as! CustomSectionHeader
header.setupCornerRadious()
let sectionButton = header.expandBtn
sectionButton?.setTitle(String(section),
for: .normal)
sectionButton?.tag = section
sectionButton?.addTarget(self,action: #selector(self.hideSection(sender:)), for: .touchUpInside)
return header
}
#objc
private func hideSection(sender: UIButton) {
let section = sender.tag
func indexPathsForSection() -> [IndexPath] {
var indexPaths = [IndexPath]()
for row in 0..<self.tableViewData[section].count {
indexPaths.append(IndexPath(row: row,
section: section))
}
return indexPaths
}
if self.hiddenSections.contains(section) {
self.hiddenSections.remove(section)
self.historyTableView.insertRows(at: indexPathsForSection(),
with: .fade)
} else {
self.hiddenSections.insert(section)
self.historyTableView.deleteRows(at: indexPathsForSection(),
with: .fade)
}
}
With out sections also you can achieve this. To do this,
1.Return cell height as section height. If user clicks on the cell then return total content height to the particular cell.
2.You need to take an array, if user selects cell, add indexPath number in to array. If selects already expand cell remove it from array. In height for row at index check indexPath is in array or not.
This is one of the way. With sections also you can do that.
//MARK:- UITableView Related Methods
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrDict.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
// var cel = tblExpandedTest.dequeueReusableCellWithIdentifier("expCell", forIndexPath: indexPath) as! CDTableViewCell
var cel : CaseHearingTabTVC! = tableView.dequeueReusableCell(withIdentifier: "caseHearingTabCell") as! CaseHearingTabTVC
if(cel == nil)
{
cel = Bundle.main.loadNibNamed("caseHearingTabCell", owner: self, options: nil)?[0] as! CaseHearingTabTVC;
}
//cell?.backgroundColor = UIColor.white
cel.delegate = self
if indexPath != selctedIndexPath{
cel.subview_desc.isHidden = true
cel.subview_remarks.isHidden = true
cel.lblHearingTime.isHidden = true
}
else {
cel.subview_desc.isHidden = false
cel.subview_remarks.isHidden = false
cel.lblHearingTime.isHidden = false
}
return cel
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectIndex = true;
if(selectedInd == indexPath.row) {
selectedInd = -1
}
else{
let currentCell = tableView.cellForRow(at: indexPath)! as! CaseHearingTabTVC
cellUpdatedHeight = Float(currentCell.lblHearingTime.frame.origin.y + currentCell.lblHearingTime.frame.size.height) + 2;
selectedInd = -1
tblCaseHearing.reloadData()
selectedInd = indexPath.row
}
let previousPth = selctedIndexPath
if indexPath == selctedIndexPath{
selctedIndexPath = nil
}else{
selctedIndexPath = indexPath
}
var indexPaths : Array<IndexPath> = []
if let previous = previousPth{
indexPaths = [previous]
}
if let current = selctedIndexPath{
indexPaths = [current]
}
if indexPaths.count>0{
tblCaseHearing.reloadRows(at: indexPaths, with: UITableView.RowAnimation.automatic)
}
}
func tableView(_ tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowIndexPath indexPath:IndexPath) {
(cell as! CaseHearingTabTVC).watchFrameChanges()
}
func tableView(_ tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowIndexPath indexPath:IndexPath) {
(cell as! CaseHearingTabTVC).ignoreFrameChanges()
}
func tableView(_ TableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{
if indexPath == selctedIndexPath{
return CGFloat(cellUpdatedHeight)
}else{
return CaseHearingTabTVC.defaultHeight
}
}
Best approach is to create two different cells for normal card and expanded card.
fileprivate var selectedIndex: Int?
func registerTableViewCells() {
tableView.register(UINib(nibName:Nib.CardCell , bundle: nil), forCellReuseIdentifier: "CardCell")
tableView.register(UINib(nibName:Nib.ExpandedCardCell , bundle: nil), forCellReuseIdentifier: "ExpandedCardCell")
}
override func viewDidLoad() {
super.viewDidLoad()
self.registerTableViewCells()
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
guard let index = selectedIndex else {
return 115
}
if index == indexPath.row{
return 200
}
return 115
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let selected = selectedIndex, selected == indexPath.row{
let cell = tableView.dequeueReusableCell(withIdentifier: "ExpandedCardCell", for: indexPath) as! ExpandedCardCell
return cell
}
let cell = tableView.dequeueReusableCell(withIdentifier: "CardCell", for: indexPath) as! CardCell
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if selectedIndex == indexPath.row{
selectedIndex = nil
}
else{
selectedIndex = indexPath.row
}
UIView.performWithoutAnimation {
tableView.reloadData()
}
}
I have a tableview. In the tableview cell I have a label and switch. Here I want to deselect the row when switch is off.
Here is my code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! BM_MyBusinessTableViewCell
cell.tapSwitch.tag = indexPath.row
cell.businessLabel.text = labelArray[indexPath.row]
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
Don't select/deselect the cell when the switch is tapped. Just store the indexPath.row of the selected switches and reload the tableview.
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
let labelArray = ["Employees", "Break Time Setup", "Employee Timeoff", "Reports", "Messages"]
var selectedIndexPaths = [Int]()
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return labelArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! Cell
cell.selectionStyle = .none
cell.tapSwitch.isOn = selectedIndexPaths.contains(indexPath.row)
cell.tapSwitch.tag = indexPath.row
cell.tapSwitch.addTarget(self, action: #selector(tapSwitchAction(_:)), for: .valueChanged)
cell.businessLabel.text = labelArray[indexPath.row]
return cell
}
#objc func tapSwitchAction(_ sender: UISwitch) {
if sender.isOn {
selectedIndexPaths.append(sender.tag)
} else {
selectedIndexPaths.removeAll { $0 == sender.tag }
}
tableView.reloadData()
}
}
Then you can get the selected row values anywhere like this
#objc func getSelectedValues() {
let selectedLabelArray = labelArray.enumerated().filter { selectedIndexPaths.contains($0.offset) }
print(selectedLabelArray)
}
Update
Option 1
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if selectedIndexPaths.contains(indexPath.row) {
selectedIndexPaths.removeAll { $0 == indexPath.row }
} else {
selectedIndexPaths.append(indexPath.row)
}
tableView.reloadData()
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
//do nothing
}
Option 2
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? BM_MyBusinessTableViewCell {
cell.tapSwitch.isOn = !cell.tapSwitch.isOn
tapSwitchAction(cell.tapSwitch)
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? BM_MyBusinessTableViewCell {
cell.tapSwitch.isOn = !cell.tapSwitch.isOn
tapSwitchAction(cell.tapSwitch)
}
}
I have a table view. I am using multiple cell selection. Everything is working correctly, functionality wise, but UI wise it is not. Whenever I select a cell and scroll down I see the color is changed in another cell below though that cell was never actually selected. What I have done is this for the cell:
class FollowSportsCell: UITableViewCell {
#IBOutlet weak var sportL: UILabel!
#IBOutlet weak var backImg: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
override func prepareForReuse() {
super.prepareForReuse()
backImg.backgroundColor = UIColor(hexString: "E6E6E6")
sportL.textColor = .black
}
And, here are delegates.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sportsArr!.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) as! FollowSportsCell
let sport = sportsArr![indexPath.row]["id"] as! Int
cell.sportL.text = sportsArr![indexPath.row]["title"] as? String
cell.selectionStyle = UITableViewCell.SelectionStyle.none
if selectedSports.contains(sport) {
cell.sportL.textColor = .white
cell.backImg.backgroundColor = UIColor(hexString: "4293CC")
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedCell += 1
let sport = sportsArr![indexPath.row]["id"]
selectedSports.append(sport! as! Int)
if selectedCell > 1
{
collectionB[0].backgroundColor = UIColor(hexString: "4293CC")
collectionB[0].isEnabled = true
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
selectedCell -= 1
selectedSports = selectedSports.filter{$0 != sportsArr![indexPath.row]["id"] as! Int}
if selectedCell < 2
{
collectionB[0].backgroundColor = .lightGray
collectionB[0].isEnabled = false
}
}
When, the number is low like 4 or 5 and the scroll doesn't appear everything is good, but once they are like 20-22 then, I get this issue. Any help?
You should handle background color in tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) .
Check and use below code. Hope it will work
var selectedCells = Array<NSInteger>()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sportsArr!.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) as! FollowSportsCell
cell.sportL.text = sportsArr![indexPath.row]["title"] as? String
cell.selectionStyle = UITableViewCell.SelectionStyle.none
if self.selectedCells.contains(indexPath.row) {
cell.sportL.textColor = .white
cell.backImg.backgroundColor = UIColor(hexString: "4293CC")
if self.selectedCells.count > 1
{
collectionB[0].backgroundColor = UIColor(hexString: "4293CC")
collectionB[0].isEnabled = true
}
}
else
{
//Here Set your default color for cell backImgr background color
cell.sportL.textColor = // set default color
cell.backImg.backgroundColor = // set default color
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! FollowSportsCell
if self.selectedCells.contains(indexPath.row) {
//Here you will get selected cell and going to deselect...Do anything with deselection
if let index = self.selectedCells.index{$0 == indexPath.row}
{
self.selectedCells.remove(at: index)
}
cell.sportL.textColor = .black
cell.backImg.backgroundColor = UIColor(hexString: "E6E6E6")
selectedCell -= 1
selectedSports = selectedSports.filter{$0 != sportsArr![indexPath.row]["id"] as! Int}
if self.selectedCells.count < 2
{
collectionB[0].backgroundColor = .lightGray
collectionB[0].isEnabled = false
}
}
else
{
self.selectedCells.append(indexPath.row)
print(cell.sportL.text!)
selectedCell += 1
let sport = sportsArr![indexPath.row]["id"]
selectedSports.append(sport! as! Int)
}
self.yourtblView.reloadData()
}
Please select your default and selected color in "CellForRowAtIndexPAth". Please check the below code.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) as! FollowSportsCell
cell.sportL.text = sportsArr![indexPath.row]["title"] as? String
cell.selectionStyle = UITableViewCell.SelectionStyle.none
let sport = sportsArr![indexPath.row]["id"]
cell.sportL.textColor = default cell colour
cell.backImg.backgroundColor = default cell colour
if selectedSports.contain(sport) {
cell.sportL.textColor = required cell colour
cell.backImg.backgroundColor = required cell colour
}
return cell
}
import UIKit
class TableVC: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var tableView : UITableView!
var arrayOfTitle : [titleOfArray] = [titleOfArray]()
override func viewDidLoad() {
super.viewDidLoad()
if self.tableView != nil {
self.tableView.delegate = self
self.tableView.dataSource = self
}
for i in 0...20 {
self.arrayOfTitle.append(titleOfArray(title: "Test\(i)", isSelectedIndex: false))
}
// Do any additional setup after loading the view.
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 80
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.arrayOfTitle.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell")
cell?.textLabel!.text = self.arrayOfTitle[indexPath.row].title
cell?.textLabel!.textColor = self.arrayOfTitle[indexPath.row].isSelectedIndex ? UIColor.red : UIColor.blue
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
for i in 0...self.arrayOfTitle.count-1 {
self.arrayOfTitle[i].isSelectedIndex = false
}
self.arrayOfTitle[indexPath.row].isSelectedIndex = true
tableView.reloadData()
}
}
class titleOfArray : NSObject {
var title : String!
var isSelectedIndex : Bool!
init(title:String! ,isSelectedIndex :Bool) {
self.title = title
self.isSelectedIndex = isSelectedIndex
}
}
this might be helpful
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == table1{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! acntTableViewCell
cell.account.text = account[indexPath.row].email
return cell
}
else if tableView == table2 {
let cell2 = tableView.dequeueReusableCell(withIdentifier: "cell2")
as! popTableViewCell
cell2.pop.text = pop[indexPath.row].answer
return cell2
}
}//its give me error here Missing return in function
I am going to fill two different tables in one viewcontroller. when I return cell it give me error Missing return in function where I am doing wrong can any one suggest me what's wrong with this code
In the first place, you should compare tables using === (references), not ==.
This is one of the cases when an assertion failure is a good way to tell the compiler that no other way of the function exists e.g.:
if tableView === table1 {
return ...
} else if tableView === table2 {
return ...
} else {
fatalError("Invalid table")
}
You can also use a switch:
switch tableView {
case table1:
return ...
case table2:
return ...
default:
fatalError("Invalid table")
}
Both answers are correct, but I believe the best way to do it would be to separate each table view to have its own data source object, not a view controller. Putting multiple tableview data source protocols adds a decent amount of unnecessary code, and if you refactor them into separate objects, you can help avoid a Massive View Controller.
class FirstTableViewDataSource : NSObject, UITableViewDataSource {
var accounts: [ObjectTypeHere]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return accounts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! AcntTableViewCell
cell.account.text = accounts[indexPath.row].email
return cell
}
}
class SecondTableViewDataSource : NSObject, UITableViewDataSource {
var pops: [ObjectTypeHere]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return pops.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! PopTableViewCell
cell.account.text = pops[indexPath.row].answer
return cell
}
}
From there, just update the tableviews to pull from these objects
override func viewDidLoad() {
super.viewDidLoad()
self.table1.dataSource = FirstTableViewDataSource()
self.table2.dataSource = SecondTableViewDataSource()
}
The compiler is analyzing what will happen if tableView is neither table1 nor table2. If that should happen, the function will exit with nothing to return.
That's an error.
Your cellForRowAt method should always return a cell, so
Try this way
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == table1{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! acntTableViewCell
cell.account.text = account[indexPath.row].email
return cell
}
//if tableView is not table1 then
let cell2 = tableView.dequeueReusableCell(withIdentifier: "cell2")
as! popTableViewCell
cell2.pop.text = pop[indexPath.row].answer
return cell2
}
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var table1: UITableView!
#IBOutlet weak var table2: UITableView!
let firstClassRef = FirstTableView()
let secondClassRef = SecondTableView()
override func viewDidLoad() {
super.viewDidLoad()
firstClassRef.array1 = ["1","2","3"]
secondClassRef.array2 = ["1","2","3","1","2","3"]
self.table1.dataSource = firstClassRef
self.table2.dataSource = secondClassRef
self.table1.delegate = firstClassRef
self.table2.delegate = secondClassRef
self.table1.reloadData()
self.table2.reloadData()
}
}
class FirstTableView: NSObject, UITableViewDataSource, UITableViewDelegate {
var array1 = Array<Any>()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return array1.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as UITableViewCell
cell.textLabel?.text = array1[indexPath.row] as? String
cell.backgroundColor = UIColor.yellow
return cell
}
}
class SecondTableView: NSObject, UITableViewDataSource, UITableViewDelegate {
var array2 = Array<Any>()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return array2.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as UITableViewCell
cell.textLabel?.text = array2[indexPath.row] as? String
cell.backgroundColor = UIColor.yellow
return cell
}
}
Use Switch Statement
import UIKit
class ViewController: UIViewController , UITableViewDelegate , UITableViewDataSource {
#IBOutlet weak var topTableView: UITableView!
#IBOutlet weak var downTableview: UITableView!
var topData : [String] = []
var downData = [String]()
override func viewDidLoad() {
super.viewDidLoad()
topTableView.delegate = self
downTableview.delegate = self
topTableView.dataSource = self
downTableview.dataSource = self
for index in 0...20 {
topData.append("Top Table Row \(index)")
}
for index in 10...45 {
downData.append("Down Table Row \(index)")
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var numberOfRow = 1
switch tableView {
case topTableView:
numberOfRow = topData.count
case downTableview:
numberOfRow = downData.count
default:
print("Some things Wrong!!")
}
return numberOfRow
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = UITableViewCell()
switch tableView {
case topTableView:
cell = tableView.dequeueReusableCell(withIdentifier: "topCell", for: indexPath)
cell.textLabel?.text = topData[indexPath.row]
cell.backgroundColor = UIColor.green
case downTableview:
cell = tableView.dequeueReusableCell(withIdentifier: "downCell", for: indexPath)
cell.textLabel?.text = downData[indexPath.row]
cell.backgroundColor = UIColor.yellow
default:
print("Some things Wrong!!")
}
return cell
}
}
I want to use XMSegmentController(https://cocoapods.org/?q=segmen) to change the different tableview,I do not know what is missing in my program, which leads to a black situation when I run. Does anyone know what to add to my program? Thank you.
Here is mt code:
import UIKit
import XMSegmentedControl
class ViewController: UIViewController, XMSegmentedControlDelegate,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var segmentedControl1: XMSegmentedControl!
#IBOutlet weak var tableview1: UITableView!
#IBOutlet weak var tableview2: UITableView!
let one = ["1","2","3"]
let two = ["4","5","6"]
override func viewDidLoad() {
super.viewDidLoad()
segmentedControl1.delegate = self
segmentedControl1.segmentTitle = ["One", "Two"]
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "left", for: indexPath)
cell.textLabel?.text = one[indexPath.row]
return cell
}else {
let cell = tableView.dequeueReusableCell(withIdentifier: "right", for: indexPath)
cell.textLabel?.text = two[indexPath.row]
return cell
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == self.tableview1 {
return one.count
}
return two.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func xmSegmentedControl(_ xmSegmentedControl: XMSegmentedControl, selectedSegment: Int) {
if xmSegmentedControl == segmentedControl1 {
print("SegmentedControl1 Selected Segment: \(selectedSegment)")
}
}
}
Set your controller as initial ViewController to show your Controller. Now use selectedSegment argument from delegate method and hide/show the tableView according to it.
func xmSegmentedControl(_ xmSegmentedControl: XMSegmentedControl, selectedSegment: Int) {
if xmSegmentedControl == segmentedControl1 {
tableview1.isHidden = selectedSegment != 0
tableview2.isHidden = selectedSegment != 1
}
}
Also instead of using two tableView you can use single tableView like this.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if segmentedControl1.selectedSegment == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "left", for: indexPath)
cell.textLabel?.text = one[indexPath.row]
return cell
}else {
let cell = tableView.dequeueReusableCell(withIdentifier: "right", for: indexPath)
cell.textLabel?.text = two[indexPath.row]
return cell
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if segmentedControl1.selectedSegment == 0 {
return one.count
}
return two.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
And in delegate method of xmSegmentedControl simply reload the tableView.
func xmSegmentedControl(_ xmSegmentedControl: XMSegmentedControl, selectedSegment: Int) {
if xmSegmentedControl == segmentedControl1 {
tableView.reloadData()
}
}
what is your initial ViewController?can you please check in your storyboard?
set an initial viewcontroller.
func xmSegmentedControl(_ xmSegmentedControl: XMSegmentedControl, selectedSegment: Int) {
if xmSegmentedControl == segmentedControl1 {
tableviewOne.isHidden = selectedSegment != 0
tableviewSecond.isHidden = selectedSegment != 1
}
}