How to custom order two different sections in a tableview Swift - ios

I have successfully implemented two different sections in my table view. Section 1 has 3 cells displayed first, then section 2 has 12 displayed afterwards.
I would like to have it ordered so section 1 has its 3 cells mixed into section 2 (12 cells) So in this case it would be displayed every 4 cells. I would like to code it in a way that when the section 2 cells increases over time it keeps section 1 every 4 cells.
Here is the tableview delegate functions I have at the moment
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 2
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
if (section == 0) {
return 3 // At the moment I have hard coded it will change it to array.count
} else {
return eventNameArray.count
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("MovingCell", forIndexPath: indexPath) as! WhatsOnMovingTableViewCell
// Do something!
return cell
}
else {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! WhatsOnTableViewCell
// Do something!
return cell
}
}

You cannot mix the cells of different sections.
Since that is what you want the solution is to remove the sections all together or include more sections:
Solution 1:
1 Section with x cells: Cell|Cell|Cell|Cell|MovingCell|Cell|Cell|Cell|Cell|Moving Cell
Solution 2: y Sections with 1 or z cells - Cell|Cell|Cell|Cell + MovingCell + Cell|Cell|Cell|Cell + Moving Cell
I will show you the code that would be needed for Solution 1. You will need to have some variable indicating what the length of Cell-semi-sections would be, e.g. let cellCountBeforeMoving = 4:
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3 + eventNameArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if (indexPath.item + 1) % (cellCountBeforeMoving + 1) == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("MovingCell", forIndexPath: indexPath) as! WhatsOnMovingTableViewCell
// Do something!
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! WhatsOnTableViewCell
// Do something!
return cell
}
}
Note the indexes are now a little offset and you have to be careful accessing the array. The probably correct way to get the element corresponding to a given indexPath is
eventNameArray[indexPath.item - ((indexPath.item + 1) / (cellCountBeforeMoving + 1))]
Solution 1 will end up something like: (you need some var which gives you the number of interplaced MovingCells)
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return movingCells * 2
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section % 2 == 1 {
return 1
}
return cellCountBeforeMoving
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.section % 2 == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("MovingCell", forIndexPath: indexPath) as! WhatsOnMovingTableViewCell
// Do something!
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! WhatsOnTableViewCell
// Do something!
return cell
}
}

Related

Index out of range in tableView

I am trying to display 2 different types of data in table view. The videoNews Array only has one element that is to be displayed in indexPath.row == 1 and Suggested News array has many elements that are to be displayed in indexPath.row >= 4. Everything in between are just labels and go as it is. The problem comes when elements from SuggestedNews array are displayed the tableView gives index out of range error even though the array has elements and numberOfRowsInSection also gets the right number of elements.
Code of TableView
var SuggestedNews = [VideoNews]()
var videoNews = [VideoNews]()
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (5 + SuggestedNews.count)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
if let cell = tableView.dequeueReusableCell(withIdentifier: "VideoArticleCell", for: indexPath) as? VideoArticleCell {
let video = self.videoNews[indexPath.row]
cell.updateUI(video: video)
return cell
}
} else if indexPath.row == 1 {
if let cell = tableView.dequeueReusableCell(withIdentifier: "VideoFirstLabelCell") {
return cell
}
} else if indexPath.row == 2 {
if let cell = tableView.dequeueReusableCell(withIdentifier: "VideoSubmissionCell", for: indexPath) as? VideoSubmissionCell {
return cell
}
} else if indexPath.row == 3 {
if let cell = tableView.dequeueReusableCell(withIdentifier: "VideoSecondLabelCell") {
return cell
}
} else if indexPath.row >= 4 {
if let cell = tableView.dequeueReusableCell(withIdentifier: "VideoSuggestionCell", for: indexPath) as? VideoSuggestionCell {
let latest = self.SuggestedNews[indexPath.row] //Index out of range
cell.updateUI(latest: latest)
return cell
}
}
return UITableViewCell()
}
If index.row == 4 your code in this line but you want to show first element of array; therefore, your first array index is equal to 0.
let latest = self.SuggestedNews[indexPath.row - 4]
If you have 4 cell different than SuggestedNews, your return don't be return (5 + SuggestedNews.count)
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (4 + SuggestedNews.count)
}

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.

How do I have two separate cells with two different heights? [duplicate]

This question already has answers here:
UITableview with more than One Custom Cells with Swift
(7 answers)
Swift: How to set dynamic cell height in TableViewController which contains more than one cell
(2 answers)
Closed 5 years ago.
I have two custom cells, but having trouble setting static heights to both those cells, I need the first cell to have a height of 100, but every other cell to have a height of 40. The below code makes all the cells have a height of a 100 instead of just the first one.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if(indexPath.row == 0) {
return 100.0
}
return 40.0
}
You can put your first cell in a different section.
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return 1
}else {
return yourArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! FirstCustomCell
return cell
}else{
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! SecondCustomCell
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == 1 {
return 100
} else{
return 40
}

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
}

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