This is the screen shot. According to this how to list the data in the tableview:
Already I have code as below.
func numberOfSections(in tableView: UITableView) -> Int {
return questionViewModel.numberOfSections()
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 100
} func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let identifier = "HeaderCell"
var headercell: questionheader! = tableView.dequeueReusableCell(withIdentifier: identifier) as? questionheader
if headercell == nil {
tableView.register(UINib(nibName: "questionheader", bundle: nil), forCellReuseIdentifier: identifier)
headercell = tableView.dequeueReusableCell(withIdentifier: identifier) as? NH_questionheader
} headercell.setReviewData(reviews:questionViewModel.titleForHeaderInSection(atsection:section))
headercell.isUserInteractionEnabled = false
return headercell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return questionViewModel.numberOfRowsIn(section: section)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let model = questionViewModel.titleForHeaderInSection(atsection: indexPath.section)
print(model.answerType)
print(model.answerType?.rawValue)
let c = model.answerType
return c!.cellType().getHeight()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let model = questionViewModel.titleForHeaderInSection(atsection: indexPath.section)
print(model.answerType)
print(model.answerType?.rawValue)
let c = model.answerType
let cellClass = c?.cellType().getClass()
print(cellClass)
let cell = tableView.dequeueReusableCell(withIdentifier: (cellClass?.cellReuseIdentifier())!, for: indexPath) as! BaseCell
print(cell)
cell.selectionStyle = .none
let optionModel = questionViewModel.datafordisplay(atindex: indexPath)
cell.setOptions(Options1: optionModel)
cell.delegate = self
if optionModel.isSelected!
{
print(optionModel.isSelected)
cell.setOptions1(OptionsSelected:optionModel)
}
else {
print(optionModel.isSelected)
cell.setOptions1(OptionsisSelected:optionModel)
}
cell.type = c?.cellType()
print(cell.type)
else if cell.type == .radiotype{
cell.selectionStyle = .none
}
return cell
}
This is my code. But according to this I will get the output as below screen shot.
Actually initially I need to display the section header as: - Please tell about us
After that there is subsection. The subsection questions header are as below: -1. knowledge 2. friendly or not
Then in the subsections display the options. How to do implement?
You can just display "Please tell us about" as UILabel above the table.
Below example may help you out.
let sections = [ // All sections
[ // Sports section
["Baseball", "Softball", "Cricket"], // Bat-and-Ball sub-section
["Field Hockey", "Ice Hockey", "Roller Hockey"] // Hockey subsection
], [ // Engineering section
["Software Engineer", "Electrical Engineer"] // Computer Science subsection
]
]
func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let sectionItems = sections[section]
var numberOfRows: Int = sectionItems.count // For second level section headers
for rowItems: [Any] in sectionItems as? [[Any]] ?? [] {
numberOfRows += rowItems.count // For actual table rows
}
return numberOfRows
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var sectionItems = sections[indexPath.section]
var sectionHeaders = self.sectionHeaders[indexPath.section]
let itemAndSubsectionIndex: IndexPath? = computeItemAndSubsectionIndex(for: indexPath)
let subsectionIndex = Int(itemAndSubsectionIndex?.section ?? 0)
let itemIndex: Int? = itemAndSubsectionIndex?.row
if (itemIndex ?? 0) < 0 {
// Section header
let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "SECTION_HEADER_CELL", for: indexPath)
cell.textLabel?.text = sectionHeaders[subsectionIndex] as? String
return cell
}
else{
let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "ROW_CONTENT_CELL", for: indexPath)
cell.textLabel?.text = sectionItems[subsectionIndex][itemIndex ?? 0] as? String
return cell
}
}
func computeItemAndSubsectionIndex(for indexPath: IndexPath?) -> IndexPath? {
var sectionItems = sections[Int(indexPath?.section ?? 0)]
var itemIndex: Int? = indexPath?.row
var subsectionIndex: Int = 0
for i in 0..<sectionItems.count {
// First row for each section item is header
itemIndex = (itemIndex ?? 0) - 1
// Check if the item index is within this subsection's items
let subsectionItems = sectionItems[i] as? [Any]
if (itemIndex ?? 0) < Int(subsectionItems?.count ?? 0) {
subsectionIndex = i
break
} else {
itemIndex = itemIndex! - (subsectionItems?.count)!
}
}
return IndexPath(row: itemIndex ?? 0, section: subsectionIndex)
}
And for objective-C Help you may following URL
http://sapandiwakar.in/nested-sections-in-uitableview/
Related
I am working on a nested table view. with 3 table views one inside another, the two of the table views were working properly but the super table view's cells were not adjusting as per the respective content size. even I used. UITableView.automaticDimension
1st tableView in UIViewController
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
let count = AllTaskManager.shared.futureListArray.count
isNoData(count: count)
print(count)
return count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "FutureAppointCell") as! FutureAppointCell
cell.setData(index: indexPath.row)
cell.delegate = self
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{
return UITableView.automaticDimension
}
2nd TableView inside the FutureAppointCell
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
tableHight.constant = CGFloat(AllTaskManager.shared.futureListDateArray.count * (Int(internalCellHeight) + 250))
self.delegate?.cellHeight(tableHight.constant)
return AllTaskManager.shared.futureListDateArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "FutureAppoinmentDayCell") as! FutureAppoinmentDayCell
cell.setData(index: indexPath.row)
cell.delegate = self
buttonTag = indexPath.row
let startDate = AllTaskManager.shared.convertStringToDate(string: cell.dateFullName)
print("\(startDate) is the date" )
if startDate.month >= Date().month{
if startDate.month == Date().month{
if startDate.day == Date().day{
cell.cancelBTN.isHidden = true
cell.addToCalenderBTN.frame.size.width = 20
}else{
cell.cancelBTN.isHidden = false
cell.cancelBTN.addTarget(self, action: #selector(cancelBtn(sender:)), for: .touchUpInside)
}
}else {
cell.cancelBTN.isHidden = false
cell.cancelBTN.addTarget(self, action: #selector(cancelBtn(sender:)), for: .touchUpInside)
}
}else {
cell.cancelBTN.isHidden = true
}
cell.addToCalenderBTN.addTarget(self, action: #selector(addToCalendar(sender:)), for: .touchUpInside)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{
return UITableView.automaticDimension
}
3rd Table view in FutureAppoinmentDayCell
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
tableHeight.constant = CGFloat(count * 65)
self.delegate?.cellHeight(tableHeight.constant)
return count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "FutureNoBtnTableViewCell", for: indexPath) as! FutureNoBtnTableViewCell
print(getDict(subIndex: indexPath.row))
let dict = getDict(subIndex: indexPath.row)
cell.employeeLBL.text = dict.value(forKey: "serviceDisplayName") as? String
let time = AllTaskManager.shared.getSubHeaderTimeForPastFutureName(string: dict.value(forKey: "startDateTime") as! String)
cell.timeLBL.text = time
cell.appointmentId = dict.value(forKey: "appointmentId") as? String
cell.id = dict.value(forKey: "id") as? String
cell.time = dict.value(forKey: "startDateTime") as? String
if let startDate = dict.value(forKey: "startDateTime") as? String {
let date = AllTaskManager.shared.convertStringToDate(string: startDate )
if date.year == Date().year{
if date.month == Date().month{
if date.day == Date().day{
//"transitionStateDisplayValue": "Checked In", "transitionStateDisplayValue": "Booked",
if let checkiInStatus = dict.value(forKey: "transitionStateDisplayValue") as? String{
cell.delegate = self
if checkiInStatus == "Checked In"{
cell.checkInBTN.isHidden = true
cell.checkedInLBL.isHidden = false
}else{
cell.checkInBTN.setTitle("Check-In", for: .normal)
}
}else{
cell.checkInBTN.isHidden = true
}
}else {
cell.checkInBTN.isHidden = true
}
}else{
cell.checkInBTN.isHidden = true
}
}else{
cell.checkInBTN.isHidden = true
}
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{
return 60
}
I often use stack views in table view cells, and adjust cell height according to stack view. Maybe this will solve your problem
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 am trying to load my different controller using Expandable Tableview but my headerview is set
as switch condition
For Header XXX1 -> two sub menu a and b ..
For Header XXX2-> sub menu c
but for Header XXX3 no sub menu ,, So i will work on click with XXX3(currently working with check SectionData.count == 0 ) but for multiple how to manage .. check out my code
sectionNames = ["xxxx1","xxxx2","xxx3","xxxx4"] //this is main header
sectionItems = [ ["a","b"],[c],[],[],[],[],[],[]]// This is sub menu items
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (self.expandedSectionHeaderNumber == section) {
let arrayOfItems = self.sectionItems[section] as! NSArray
return arrayOfItems.count;
} else {
return 0;
}
//return arraylist.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if (self.sectionNames.count != 0) {
return self.sectionNames[section] as? String
}
return ""
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 60.0;
}
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 50))
return footerView
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 0.5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifer, for: indexPath)
let section = self.sectionItems[indexPath.section] as! NSArray
cell.textLabel?.textColor = UIColor.black
cell.textLabel?.text = section[indexPath.row] as? String
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0 {
}
let indexPath = tableView.indexPathForSelectedRow
// print(indexPath as Any)
//getting the current cell from the index path
let currentCell = tableView.cellForRow(at: indexPath!)! as UITableViewCell
// print(currentCell as Any)
//getting the text of that cell
let currentItem = currentCell.textLabel!.text
print(currentItem!)
switch currentItem {
case "XXXX1":
//// Here unable to do any work
break
case "a":
APICalla()
case "b":
APICallb ()
default:
break
}
return
}
Using this link
Sorry this tutorial is quite poor.
Swift is an object oriented language so use a custom model, a generic Section object with name, items and the information if the section is collapsed
class Section<T> {
var name : String
var items = [T]()
var isCollapsed = false
init(name : String, items : [T] = []) {
self.name = name
self.items = items
}
}
and a suitable struct for the items with a title and a closure to be called in didSelect
struct Item {
let title : String
let selectorClosure : (() -> Void)?
}
Rather than using multiple arrays populate the data source array consistently
var sections = [Section<Item>(name:"xxxx1", items: [Item(title: "a", selectorClosure: APICalla), Item(title: "b", selectorClosure: APICallb)]),
Section<Item>(name:"xxxx2", items: [Item(title: "c", selectorClosure: APICallc)]),
Section<Item>(name:"xxxx3")]
In numberOfRowsInSection return the proper number of items depending on isCollapsed
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let currentSection = sections[section]
return (currentSection.isCollapsed) ? 0 : currentSection.items.count
}
In cellForRow don't use typeless Foundation collection types
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifer, for: indexPath)
let item = sections[indexPath.section].items[indexPath.row]
cell.textLabel?.textColor = UIColor.black
cell.textLabel?.text = item.title
return cell
}
In the method to collapse/expand the sections just toggle isCollapsed
let currentSection = sections[section]
currentSection.isCollapsed.toggle()
and perform the animation
titleForHeaderInSection is much simpler, too
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sections[section].name
}
In didSelectRow never get any data from the view (the cell) get it from the model (the data source array) and call the selector closure. With this logic a switch is not needed.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
let item = sections[indexPath.section].items[indexPath.row]
item.selectorClosure?()
}
Swift4 I think this will helps you
// declare globally
var isExpanded : Bool = true
var indexOfSection = Int()
var yourArray = [ModelName]()
override func viewDidLoad() {
super.viewDidLoad()
indexOfSection = 999
}
extension ViewController: UITableViewDelegate, UITableViewDataSource
{
func numberOfSections(in tableView: UITableView) -> Int {
if yourArray.count > 0{
return yourArray.count
}else{
return 0
}
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView(frame: CGRect(x: view.frame.origin.x,y: 0 , width: view.frame.size.width ,height: 60))
headerView.backgroundColor = .white
let collapseBtn = UIButton(frame: CGRect(x: headerView.frame.origin.x,y: headerView.frame.origin.y , width: view.frame.size.width ,height: 60))
collapseBtn.addTarget(self, action: #selector(expandSection(sender:)), for: .touchUpInside)
collapseBtn.tag = section
collapseBtn.backgroundColor = .clear
headerView.addSubview(collapseBtn)
return headerView
}
#objc func expandSection(sender:UIButton){
print(sender.tag)
if isExpanded == true{
indexOfSection = sender.tag
mIdeaTableView.reloadData()
isExpanded = false
mTableView.reloadSections([indexOfSection], with: UITableView.RowAnimation.bottom)
}else{
indexOfSection = 999
isExpanded = true
self.mTableView.reloadData()
}
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 60
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if yourArray.count > 0{
if yourArray[section].items!.count > 0{
if indexOfSection == section{
return yourArray[section].items!.count
}else{
return 0
}
}else{
return 0
}
}else{
return 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: “CellID”, for: indexPath) as! Cell
if yourArray[indexPath.section]. items!.count > 0{
if yourArray[indexPath.section]. items!.count > 0{
let ideas = yourArray[indexPath.section].ideaItems
if ideas!.count > 0{
if indexOfSection == indexPath.section{
cell.mLbl.text = ideas![indexPath.row].name ?? ""
if ideas![indexPath.row].isExpanded == true{
cell.mAddImg.image = #imageLiteral(resourceName: "tick")
}else{
cell.mAddImg.image = #imageLiteral(resourceName: "edit213-1")
}
}
}
}
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 60
}
}
//Structure of my response
{
items = (
{
name = “a”;
},
{
name = “b”;
},
);
name = “xxxx1”;
}
items = (
{
name = “c”;
},
);
name = “xxxx2”;
}
}
Below I am trying to load data into a UITableView and every time the data ends up either in the wrong cell or duplicated into cells it should never had access to. I have cut out a lot of extra code and am still running into this problem. I think I am missing something fundamental about UITableViews.
func setUpFeedTable() {
self.tableFeed.isScrollEnabled = true
for i in 0 ..< allDictionary.count {
let dictionary = allDictionary[i]
if dictionary?["type"]! != nil {
let l = i
print("text", l)
self.tableFeed.cellForRow(at: IndexPath(row: l, section: 0))?.imageView?.layer.borderColor = UIColor.black.cgColor
self.tableFeed.cellForRow(at: IndexPath(row: l, section: 0))?.imageView?.layer.borderWidth = 1
self.tableFeed.cellForRow(at: IndexPath(row: l, section: 0))?.imageView?.layer.cornerRadius = 1
//self.tableFeed.cellForRow(at: IndexPath(row: i, section: 0))?.imageView?.clipsToBounds = true
self.editProfileButton.imageView?.contentMode = UIViewContentMode.scaleAspectFill
//self.tableFeed.reloadData()
//self.tableFeed.reloadRows(at: [IndexPath(row: l, section: 0)], with: UITableViewRowAnimation(rawValue: 0)!)
self.tableFeed.cellForRow(at: IndexPath(row: l, section: 0))?.imageView?.frame = CGRect(x: 0, y: UIScreen.main.bounds.height/2, width: 100, height: 100)
self.tableTextOverLays(i: l, type: Int((dictionary?["type"])! as! NSNumber))
//self.tableFeed.reloadRows(at: [IndexPath(row: l, section: 0)], with: UITableViewRowAnimation(rawValue: 0)!)
self.tableFeed.reloadDate()
}
else if (dictionary?["type_"] as! String) == "Image" {
print("image", i)
}
else {
print("video")
}
}
}
func tableTextOverLays(i: Int, type: Int){
if type == 0{
print("saw type 0", i)
self.tableFeed.cellForRow(at: IndexPath(row: i, section: 0))?.imageView?.image = #imageLiteral(resourceName: "Geo-fence-50")
}
else if type == 1 {
self.tableFeed.cellForRow(at: IndexPath(row: i, section: 0))?.imageView?.image = #imageLiteral(resourceName: "Happy-50")
}
else if type == 2 {
self.tableFeed.cellForRow(at: IndexPath(row: i, section: 0))?.imageView?.image = #imageLiteral(resourceName: "Information-50")
}
else if type == 3 {
self.tableFeed.cellForRow(at: IndexPath(row: i, section: 0))?.imageView?.image = #imageLiteral(resourceName: "Home-50")
}
}
Update: I have edited my code and things are working far better (so thank you!) but I am now running into the issue of a images being place both into the first two cells and then the 4th and 5th cells.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == self.table {
return users2.count
}
else {
//print("married barry", tableFeedCount)
return tableFeedCount
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == self.table {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath as IndexPath) as UITableViewCell
cell.textLabel?.text = self.users2[indexPath.row].name
return cell
}
else {
//print("working?")
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath as IndexPath) as UITableViewCell
let dictionary = allDictionary[indexPath.row]
if dictionary?["type"]! != nil {
cell.imageView?.layer.borderColor = UIColor.black.cgColor
cell.layer.borderWidth = 1
cell.imageView?.layer.cornerRadius = 1
cell.imageView?.frame = CGRect(x: 0, y: UIScreen.main.bounds.height/2, width: 100, height: 100)
self.tableTextOverLays(i: indexPath.row, type: Int((dictionary?["type"])! as! NSNumber), cell: cell)
}
else if (dictionary?["type_"] as! String) == "Image" {
print("image")
}
else {
print("video")
}
return cell
}
}
The reason is because you'r trying to set UITableviewCells metadata requesting cell's to the tableView, Cells are reused in UITableView protocol method cellforRowAtIndexPath and that is why you see duplicates or metadata in other cells.
What you need to do is set the metadata of each cell in cellforRowAtIndexPath method.
For example if you have an array with info like this
let metadata = ["title1", "title2", "title3"]
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return metadata.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
let title = metadata[indexPath.row]
cell.titleLabel.text = title
return cell
}
It isn't right to populate a TableView like that.
Each TableView must be related to a DataSource or to a UITableViewDelegate, and this, for example, should implement methods such as tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
For instance:
class MyViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tableView: UITableView!
var myStrings = ["1", "2", "3", "4", "5"]
override func viewDidLoad() {
self.tableView.delegate = self
self.tableView.dataSource = self
}
#available(iOS 2.0, *)
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return 1
}
return myStrings.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
#available(iOS 2.0, *)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseId", for: indexPath)
if indexPath.section == 0 {
cell.textLabel?.text = "This is the row in the first section"
} else {
cell.textLabel?.text = myStrings[indexPath.row]
}
return cell
}
}
I want to select a row from different sections of the same table-view. I am getting output that many rows are selecting but I want exactly only one selected row from each section.
Here is My Arrays:
var filterFeedUnderAll = ["Complex","NotComplex","Easy"]
var filterFeedUnderAllStocks = ["AllStocks","Portfolio","Watchlist","Sector","Ticker"]
var filterFeedUnderByDate = ["ByDate","ByComments","ByLikes"]
The methods I have used:
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 3
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
var count:Int?
if section == 0
{
count = filterFeedUnderAll.count
}
else if section == 1
{
count = filterFeedUnderAllStocks.count
}
else if section == 2
{
count = filterFeedUnderByDate.count
}
return count!
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = self.m_HomeFeedFilterBaseTableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! HomeFeedFIlterBaseTableViewCell
switch (indexPath.section)
{
case 0:
cell.m_TableItemsLabel.text = filterFeedUnderAll[indexPath.row]
case 1:
cell.m_TableItemsLabel.text = self.filterFeedUnderAllStocks[indexPath.row]
case 2:
cell.m_TableItemsLabel.text = filterFeedUnderByDate[indexPath.row]
default:
cell.m_TableItemsLabel.text = "Other"
}
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let cell = m_HomeFeedFilterBaseTableView.cellForRowAtIndexPath(indexPath) as! HomeFeedFIlterBaseTableViewCell
for selectedIndexPath: NSIndexPath in tableView.indexPathsForSelectedRows!
{
if selectedIndexPath.section == indexPath.section
{
cell.m_TableItemsLabel.textColor = selectedTextColor
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
}
I want to select one row from each section. Help me to achieve this task.
first of all you need to enable multiple selection in your tableView and then this is the code that I used to do that, note that I use a Dictionary with format [String:NSIndexPath] named selectedRows where I store one indexPath by section I do this in addSelectedCellWithSection
UPDATED for last swift
import UIKit
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate,UITextFieldDelegate {
#IBOutlet weak var tableView: UITableView!
var filterFeedUnderAll = ["Complex","NotComplex","Easy"]
var filterFeedUnderAllStocks = ["AllStocks","Portfolio","Watchlist","Sector","Ticker","bla bla bla1","bla bla bla2","bla bla bla3","bla bla bla1","bla bla bla2","bla bla bla3","bla bla bla1","bla bla bla2","bla bla bla3"]
var filterFeedUnderByDate = ["ByDate","ByComments","ByLikes"]
var selectedRows = [String:IndexPath]()
var alert : UIAlertController?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSections(in tableView: UITableView) -> Int
{
return 3
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50;
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCell(withIdentifier: "headerCell") as! mycustomHeader
let layer = CAShapeLayer()
let corners = UIRectCorner.topLeft.union(UIRectCorner.topRight)
layer.path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: headerCell.frame.width, height: headerCell.frame.height), byRoundingCorners: corners, cornerRadii:CGSize(width: 20.0, height: 20.0)).cgPath
headerCell.layer.mask = layer
return headerCell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
var count:Int?
if section == 0
{
count = filterFeedUnderAll.count
}
else if section == 1
{
count = filterFeedUnderAllStocks.count
}
else if section == 2
{
count = filterFeedUnderByDate.count
}
return count!
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! testCell
switch (indexPath.section)
{
case 0:
cell.lblName.text = filterFeedUnderAll[indexPath.row]
case 1:
cell.lblName.text = self.filterFeedUnderAllStocks[indexPath.row]
case 2:
cell.lblName.text = filterFeedUnderByDate[indexPath.row]
default:
cell.lblName.text = "Other"
}
cell.lblName.textColor = UIColor.black
if(self.indexPathIsSelected(indexPath)) {
cell.lblName.textColor = UIColor.red
}
return cell
}
func addSelectedCellWithSection(_ indexPath:IndexPath) ->IndexPath?
{
let existingIndexPath = selectedRows["\(indexPath.section)"]
selectedRows["\(indexPath.section)"]=indexPath;
return existingIndexPath
}
func indexPathIsSelected(_ indexPath:IndexPath) ->Bool {
if let selectedIndexPathInSection = selectedRows["\(indexPath.section)"] {
if(selectedIndexPathInSection.row == indexPath.row) { return true }
}
return false
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = self.tableView.cellForRow(at: indexPath) as! testCell
let previusSelectedCellIndexPath = self.addSelectedCellWithSection(indexPath);
if(previusSelectedCellIndexPath != nil)
{
let previusSelectedCell = self.tableView.cellForRow(at: previusSelectedCellIndexPath!) as! testCell
previusSelectedCell.lblName.textColor = UIColor.black
cell.lblName.textColor = UIColor.red
tableView.deselectRow(at: previusSelectedCellIndexPath!, animated: true)
}
else
{
cell.lblName.textColor = UIColor.red
}
for selectedIndexPath: IndexPath in tableView.indexPathsForSelectedRows!
{
if selectedIndexPath.section == indexPath.section
{
cell.lblName.textColor = UIColor.red
tableView.deselectRow(at: indexPath, animated: true)
}
}
}
}
Hope this helps you, for me works perfect