Creating multiple sections with custom cells - ios

So I have 2 custom cells inside a table view. Each cell has it's own individual section, "Filter" and "Sort By"
func tableView(tableView:UITableView, cellForRowAtIndexPath indexPath:NSIndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("FilterCell") as! FilterCell
// Edit cell here
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier("SortByCell") as! SortByCell
// Edit cell here
return cell
}
}
func tableView(tableView:UITableView, numberOfRowsInSection section:Int) -> Int {
return 1
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2 }
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch section {
case 0:
return "Sort By"
default:
return "Filter"
}
}
I'm trying to display each section with these headers but the problem is that both sections display the same custom cell. My assumption is that I need each section to detect what custom cell to display through the identifier but I can't seem to figure this out. I'm not sure if i should be using a switch statement neither but does seem plausible

Please dude...
func tableView(tableView:UITableView, cellForRowAtIndexPath indexPath:NSIndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("SortByCell") as! SortByCell
// Edit cell here
return cell
}
let cell = tableView.dequeueReusableCellWithIdentifier("FilterCell") as! FilterCell
// Edit cell here
return cell
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
func tableView(tableView:UITableView, numberOfRowsInSection section:Int) -> Int {
return 1
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch section {
case 0:
return "Sort By"
default:
return "Filter"
}
}

Related

TableView cells from different sections getting mixed up

I am trying to implement a tableview with two sections. Each section has one type of cell which will be needed.
So section one cells are subclassed as PendingTVC
section two cells are subclassed as ScheduledCell.
I have the follow methods implemented but the cells are getting mixed up. For example if section one has 3 cells, the first 3 cells in section 2 have a mixed up label which correlates to section one's first 3 cells. Code below:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
if arr != nil {
if section == 0 {
print("returning pending : \(pendingCount)")
return pendingCount
}
else{
print("returning scheduled count : \(scheduledCount)")
return scheduledCount
}
}
return 0
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 0 {
return "Pending"
}
else{
return "Scheduled"
}
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50.0
}
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let data = arr![indexPath.row]
if indexPath.section == 0 {
if let cell = tableView.dequeueReusableCell(withIdentifier: "Pending") as? PendingTVC{
PendingTVC.formattCell(cell: cell, data: data)
cell.selectionStyle = .none;
cell.delegate = self
return cell
}
}
else{
if let cell = tableView.dequeueReusableCell(withIdentifier: "scheduledCell") as? ScheduledCell{
print("cellforrowat in scheduledCell")
ScheduledCell.formatCell(cell: cell, data: data)
cell.selectionStyle = .none;
return cell
}
}
return UITableViewCell()
}
You should fetch your data inside your section condition. If you fetch data beforehand its ambiguous with indexpath data you require.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
if indexPath.section == 0 {
if let cell = tableView.dequeueReusableCell(withIdentifier: "Pending") as? PendingTVC{
let data = pendingarr![indexPath.row] //access pending data here
PendingTVC.formattCell(cell: cell, data: data)
cell.selectionStyle = .none;
cell.delegate = self
return cell
}
}
else{
if let cell = tableView.dequeueReusableCell(withIdentifier: "scheduledCell") as? ScheduledCell{
print("cellforrowat in scheduledCell")
let data = scheduledarr![indexPath.row] // access scheduled arr here
ScheduledCell.formatCell(cell: cell, data: data)
cell.selectionStyle = .none;
return cell
}
}
}
You're using the same data array for for both sections.
let data = arr![indexPath.row]
Here you can see you are referencing indexPath.row as your index within your data array. This means the section is irrelevant. You have at least two options...
Create a 2d array in which the first index value is your section and the second is the row. e.g. dataArray = [[test, test2, test3], [otherTest, otherTest2, otherTest3]]. This can be accessed by changing your line to:
let data = arr![indexPath.section][indexPath.row]
or
2. Create two separate arrays... one for section 1 and one for section 2. Call them within your relevant checks for sections.

Adding two Custom cells in tableView

I have a tableView on mainStoryboard with two custom cells.
I would like to set two more cells at different row.
However When I implemented the code the added cells replaces original cells. (Custom cell of "Basic grammar3" and "Basic grammar5" are disappearing.)
I was trying to find the answer but could not find out.
I have image and code added below.
import UIKit
class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tblStoryList: UITableView!
var array = PLIST.shared.mainArray
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.array.count + 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 || indexPath.row == 3 || indexPath.row == 5 {
let cell = tableView.dequeueReusableCell(withIdentifier: "HeaderCell", for: indexPath) as! HeaderCell
cell.headerTitle.text = indexPath.row == 0 ? "First Stage" : indexPath.row == 3 ? "Second Stage" : "Third Stage"
return cell
}
let cell = tableView.dequeueReusableCell(withIdentifier: "StoryTableviewCell", for: indexPath) as! StoryTableviewCell
//making plist file
let dict = self.array[indexPath.row - 1]
let title = dict["title"] as! String
let imageName = dict["image"] as! String
let temp = dict["phrases"] as! [String:Any]
let arr = temp["array"] as! [[String:Any]]
let detail = "progress \(arr.count)/\(arr.count)"
//property to plist file を぀ăȘぐ
cell.imgIcon.image = UIImage.init(named: imageName)
cell.lblTitle.text = title
cell.lblSubtitle.text = detail
cell.selectionStyle = UITableViewCellSelectionStyle.none
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0 {
return
}
tableView.deselectRow(at: indexPath as IndexPath, animated:true)
if indexPath.row == 3 {
return
}
tableView.deselectRow(at: indexPath as IndexPath, animated:true)
if indexPath.row == 5 {
return
}
tableView.deselectRow(at: indexPath as IndexPath, animated:true)
let messagesVc = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
messagesVc.object = self.array[indexPath.row - 1]
self.navigationController?.show(messagesVc, sender: self)
}
You could use sections for your table view. Now, you are returning 1 in your numberOfSections function. And it is creating only one section. If you want to use headers, you can use sections for your need. And also you can fill your table view cells with multidimendional arrays. For example:
For adjusting your section headers:
let lessonTitles = ["First Stage", "Second Stage"]
Titles for sections:
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section < lessonTitles.count {
return lessonTitles [section]
}
return nil
}
For adjusting your sections and rows:
let lessons = [["Basic Grammar 1", "Basic Grammar 2"], ["Basic Grammar 3", "Basic Grammar 4"]]
Number of sections function should be:
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return lessons.count
}
Number of rows in section should be:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return lessons[section].count
}
And creating your cells is like this:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellText = data[indexPath.section][indexPath.row]
...
}
Try like this...
func numberOfSections(in tableView: UITableView) -> Int
{
return numberOfStages
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return numberOfRowsInCurrentStage
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
return customizedCell
}
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat
{
return requiredHeight
}
func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView?
{
return stageCountView
}
You can use viewForHeaderInSection if you want to show stage count on top.
edit: The comment by raki is the much better solution (use headers). I leave this here in case you want something closer to your existing implementation.
You have to change your numbering scheme in order to insert these additional rows (and not replace existing rows). So you might want to adjust the row for the "normal" elements like this:
func adjustRow(_ row: Int) -> Int {
if row < 3 {
return row
} else if row < 5 {
return row+1
} else {
return row+2
}
}

Xcode - TableView - Multiple sections

I have multiple sections in my TableView and I'm a bit stuck to display there names in the correct section. I'm new to xcode, so this an easy one for most but not for me :s
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 2
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if section == 0 {
return areas.bars.count
} else {
return areas.clubs.count
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("barsandclubsIdentifier", forIndexPath: indexPath)
if section == 0 { // **This is where I'm stuck I can't put section -> UITableViewCell**
let bars = areas.bars
let bar = bars[indexPath.row]
cell.textLabel?.text = bar.name
return cell
} else {
let clubs = areas.clubs
let club = clubs[indexPath.row]
cell.textLabel?.text = club.name
}
}
Try this may help you :
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("barsandclubsIdentifier", forIndexPath: indexPath)
if indexPath.section == 0 { // **This is where I'm stuck I can't put section -> UITableViewCell**
let bars = areas.bars
let bar = bars[indexPath.row]
cell.textLabel?.text = bar.name
}else {
let clubs = areas.clubs
let club = clubs[indexPath.row]
cell.textLabel?.text = club.name
}
return cell
}

Creating sections with headers with two dynamic tableviewcells in Swift

I have a table view with two cells, "electionInfo" and "candidates". Candidates returns an array of the candidates, while electionInfo gives a single text body (so just one cell). I'd like to divide them into two sections with their respective headers. Right now, it gives me one header for both cells. How do I fix it?
Thanks!!
My code...
#IBOutlet weak var table: UITableView!
var info: [PFObject] = []
var items: [PFObject] = []
let titles = ["Election Info", "Candidates"]
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items.count + 1
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return self.items.count
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return titles[section]
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row == self.items.count {
let cell = table.dequeueReusableCellWithIdentifier("candidateCell") as! CandidateTableViewCell
let candidate = items[indexPath.row]
cell.candidateImage.file = candidate["image"] as! PFFile
cell.candidateImage.loadInBackground()
cell.candidateName?.text = candidate["name"] as! String
cell.candidateParty?.text = candidate["partyAffiliation"] as! String
return cell
} else {
let cell = table.dequeueReusableCellWithIdentifier("electionCell") as! ElectionInfoTableViewCell
cell.electionInfo.text = "hey there"
}
}
}
internal func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2 //or the number of sections you have
}
internal func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let cell = UITableViewCell()
if indexPath.section == 0 {
let candidateCell = table.dequeueReusableCellWithIdentifier("candidateCell") as! CandidateTableViewCell
let candidate = items[indexPath.row]
cell.candidateImage.file = candidate["image"] as! PFFile
cell.candidateImage.loadInBackground()
cell.candidateName?.text = candidate["name"] as! String
cell.candidateParty?.text = candidate["partyAffiliation"] as! String
return candidateCell
} if indexPath.section == 1 {
let electionCell = table.dequeueReusableCellWithIdentifier("electionCell") as! ElectionInfoTableViewCell
cell.electionInfo.text = "hey there"
return electionCell
}
return cell
}
then you have also to change your numberOfRowsInSection
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if section == 0 {
return self.items.count
}
if section == 1 {
return self.items.count // or the number of rows you have in that section
}
}
A section and a cell is different thing in tableview. Right now your code gives you section instead of cell because you return self.items.count + 1 in numberOfSectionsInTableView. A fix for this;
Since your tableview should contain two section only you must return 2 or titles.count in numberOfSectionsInTableView
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return self.titles.count
}
Next return corresponding array count in numberOfRowsInSection
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0{
return self.info.count
}else{
return self.items.count
}
}
And finally in cell for row at index path return cell based on a section:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.section == 1 {
let cell = table.dequeueReusableCellWithIdentifier("candidateCell") as! CandidateTableViewCell
let candidate = items[indexPath.row]
cell.candidateImage.file = candidate["image"] as! PFFile
cell.candidateImage.loadInBackground()
cell.candidateName?.text = candidate["name"] as! String
cell.candidateParty?.text = candidate["partyAffiliation"] as! String
return cell
} else {
let cell = table.dequeueReusableCellWithIdentifier("electionCell") as! ElectionInfoTableViewCell
cell.electionInfo.text = "hey there"
}
}

How to change section location of a UITableViewCell on tap

I'm trying to add a UITableViewCell to another UITableView section whenever a button on the cell is tapped. However, I'm quite confused about the process of how to change a cell's section location after it has already been loaded into the table view. Currently I have two sections and am adding 5 custom UITableViewCells into the first section.
Any ideas on how to move the cells to the second section on tap?
Here are cell and section methods in my view controller class:
var tableData = ["One","Two","Three","Four","Five"]
// Content within each cell and reusablity on scroll
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var tableCell : Task = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! Task
tableCell.selectionStyle = .None
tableView.separatorStyle = UITableViewCellSeparatorStyle.None
var titleString = "Section \(indexPath.section) Row \(indexPath.row)"
tableCell.title.text = titleString
println(indexPath.row)
return tableCell
}
// Number of sections in table
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
// Section titles
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 0 {
return "First Section"
} else {
return "Second Section"
}
}
// Number of rows in each section
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return tableData.count
} else if section == 1 {
return 0
} else {
return 0
}
}
You need to have a separate datasource for first and second sections. When button is tapped, modify datasource and move cell to new section with moveRowAtIndexPath(indexPath: NSIndexPath, toIndexPath newIndexPath: NSIndexPath) UITableView method.
For example:
var firstDataSource = ["One","Two","Three","Four","Five"]
var secondDataSource = [ ]
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return section == 0 ? firstDataSource.count : secondDataSource.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel?.text = indexPath.section == 0 ? firstDataSource[indexPath.row] : secondDataSource[indexPath.row]
return cell
}
// For example, changing section of cell when click on it.
// In your case, similar code should be in the button's tap event handler
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
if indexPath.section == 0
{
let data = firstDataSource[indexPath.row]
tableView.beginUpdates()
secondDataSource.append(data)
firstDataSource.removeAtIndex(indexPath.row)
let newIndexPath = NSIndexPath(forRow: find(secondDataSource, data)!, inSection: 1)
tableView.moveRowAtIndexPath(indexPath, toIndexPath: newIndexPath)
tableView.endUpdates()
}
}

Resources