UITableView selecting section header - ios

I'm getting weird behaviour in my TableView
I turned isUserInteractionEnabled on one of my section headers because I need to put a collectionView in it. Before I did anything I noticed that when I tap on that header view (it is a UITableViewCell) it triggers the didSelectRowAt method with the index of a first cell in that section (right below the header). Does anybody know what causes that behaviour and how to turn it off?

Your header sections are part of your UITableView.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
}
In this method indexPath return rows and section, indexPath.section
-> returns section of UitableView, you have tapped and indexPath.row -> returns down of that particular section, tapped.
So this function is going to get called no matter what you do. You
need to override the table view's gesture to avoid this.

Related

How to determine when the cells in a tableView are returned so as to add a uiview after its finished?

I'm working with some legacy code and it looks like they added a custom sticky header view in the viewDidLoad. The issues is that I need to add the sticky header view AFTER the other cells are returned so that I may send the sticky header view to the back of the other cells so it can be used as a background for the topmost cell.
like so:
homeScreenTableView.sendSubviewToBack(headerView)
or
homeScreenTableView.insertSubview(headerView, at: 0)
The issue is there is no call back after the cells are returned in a tableView. I know this is a bit hacky, but is there a way to do this?
You check if the last indexPath in indexPathsForVisibleRows array has been displayed on screen.
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if let lastVisibleIndexPath = tableView.indexPathsForVisibleRows?.last {
if indexPath == lastVisibleIndexPath {
// finished loading
}
}
}

Releasing highlighted state for UITableViewCell after returning to the screen

In UITableView, when tapping and holding a cell and (without releasing this cell) switching to another screen in tab bar and returning to the initial one, the cell remains highlighted (not selected) and if tapping on another cell, the first one gets selected.
Upon tapping and holding the first cell, tableView(_ tableView: UITableView, didHighlightRowAt indexPath: IndexPath) is called for the first cell. So far it is how it should be.
Upon tapping on another cell (after returning to the screen), tableView(_ tableView: UITableView, didUnhighlightRowAt indexPath: IndexPath) is called for the first cell. And then all methods for selection for the first cell.
Is there a way to remove this behaviour? And upon returning to the screen have no highlighted cells.
cell.setHighlighted(false, animated: false) doesn't work. Yes, it removes highlighting, but selection methods are again called for the first cell.
Have you tried to implement shouldHighlightRowAt and return false?
From the docs for tableView(_:shouldHighlightRowAt:):
Asks the delegate if the specified row should be highlighted.

How to prevent cells from indenting when using custom swipe actions in edit mode?

I'm trying to implement two cells, one that can be deleted by swiping, and one that can't be deleted, but has swipe actions the other way.
This is what it looks like now:
I don't want the middle cell to be indented when clicking Edit.
Without any custom code, all cells would show this red circle and get a delete-button, but I have added a few lines of code to prevent that.
This code will set all cells without a leading or trailing swipe action to not become editable, which explains the bottom cell in the gif. I have to include the leading swipe actions to this, because if the cell isn't editable, then I can't swipe at all.
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
let vm = sections[indexPath.section].viewModels[indexPath.row]
return vm.leadingSwipeActions != nil || vm.trailingSwipeActions != nil
}
The following code will prevent the middle cell from showing the red circle.
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
return sections[indexPath.section].viewModels[indexPath.row].trailingSwipeActions == nil ? .none : .delete
}
If I don't pass .none for the cell with leading actions, then it would show the red circle AND it would even show a default deletion-swipe. I don't want the ability to delete this row!
How can I prevent the middle cell from indenting, while still retaining the ability to swipe it?
This method seems to work! tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool
https://developer.apple.com/documentation/uikit/uitableviewdelegate/1614873-tableview?language=objc

prevent table view cells from closing after cell action

I have two action on a table view cell like such:
After I touch them, the actions get executed but the cell goes back to its original state (closed) like such:
How can I prevent the cell from closing and keep show the actions after the touch?
Are you using trailingSwipeActionsConfigurationForRowAt to show the options, if yes then it is the default swipe behavior of UITableViewCell. On any action on the + or - the cell will hide those options, it does not retain it's trailingSwipeActions and goes back to the normal visible cell state.
func tableView(_ tableView: UITableView,
trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?

Expand UITableViewCell with multiple sections

I want to expand my UITableViewCells with a UITableView that has multiple sections. The way I'm doing it is as follows:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedRowIndex = indexPath
habitTableView.beginUpdates()
habitTableView.endUpdates()
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if (selectedRowIndex != nil && indexPath == selectedRowIndex!){
return 147
}
return 90
}
However there are some strange behaviors, for example, if one cell expands it sort of "eats up" the next section header underneath it so the section header disappears. I am just wondering - is there any nuances with a UITableView that has multiple sections?
So, you can do one thing is to have two protocol type of UITableViewCell. One is for normal and another one is for expanded. Once you type on a cell, you just need to update the delegate to use expanded one instead normal one. When updating, you only need to call reloadRowsAtIndexPaths to prevent reload everything.
You only need to create one more cell prototype and have a boolean value for indicating the state. Then, add your logic to cellForRowAtIndexPath.

Resources