Good day!
I'm trying to implement the rearrangement of rows by using moveRowAt method.
My task is to fix the top row and make it not editable. I managed to make it not editable by using canEditRowAt method. But I still can change its position by putting other rows in its place.
How can I completely fix the top cell for any type of rearrangement?
Thank you in advance!
You can override the instance method tableView(_:targetIndexPathForMoveFromRowAt:toProposedIndexPath:) in UITableViewDelegate and implement as per your need. You can check out the api reference here.
Sample code would be like as follows.
override func tableView(_ tableView: UITableView, targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath, toProposedIndexPath proposedDestinationIndexPath: IndexPath) -> IndexPath {
if proposedDestinationIndexPath.row == 0 {
return IndexPath(row: 1, section: proposedDestinationIndexPath.section)
} else {
return proposedDestinationIndexPath
}
}
Hope it helps. Cheers.!
Related
I'm trying to play a reorder animation that should be called by the methods below, I guess
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
true
}
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
}
But for some reason, no animation followed. Most likely, I missed something, how exactly to trigger the animation of changing the order of the cells.
I found the missing component. The reason for which the animation of moving cells did not start. It's the lack of a setting:
tableView.isEditing = true
I have implemented two custom cells in the tableview.Now I want to replace these two custom cells with one another. How to achieve this?
Implement following tableview methods and write your code in it
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// return boolean value for a specific or all cells, you want to enable movement
}
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
// Handle array element movement along with your row/cell
}
Share your full source code better help
If you would like to reorder rows in UITableView. Take a look at two delegates that are implemented in the UITableView.
They are: tableView:canMoveRowAtIndexPath: and moveRowAtIndexPath:toIndexPath:.
Also take a look at tutorial that show how it is possible to implement.
Along with tableview delegates, use moveRow(at: <IndexPath>, to: <IndexPath>), to move your row programatically (automatically), without user interaction.
tblTabel.moveRow(at: <IndexPath>, to: <IndexPath>)
// Tableview Delegates
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// return boolean value for a specific or all cells, you want to enable movement
}
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
// Handle array element movement along with your row/cell
}
You can see my code here:
#IBAction func edit(sender: UIButton?) {
let indexPath = NSIndexPath(forRow: 0, inSection: 1)
self.tableView(tableVw, editActionsForRowAtIndexPath: indexPath)
}
It seems to that you miss the key points of UITableView behaviour. Please consider to read official documentation first: https://developer.apple.com/reference/uikit/uitableview
You got it backwards, the
optional func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?
function is called by the table view on it's delegate while you are supposed to implement it and return an array of custom actions you want displayed - it's not supposed to be called by you to signal something to the table view.
https://developer.apple.com/reference/uikit/uitableviewdelegate/1614956-tableview
I am trying to learn Swift, but there is a problem in my project that drives me nuts.
I have a working list of data in a ViewController fed by parse.com. I managed to implement a swipe-feature that reveals buttons for both deleting and editing. That is working fine. Now I want the user to be able to reorder the cells. So I successfully implemented a button to put the table into editing-mode. My 2 problems with that are:
When I enter edit-mode I just want to be able to reorder the cells since editing and deleting is done via swipe (via "tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath)". How can I achive that the user doesn't see the 2 buttons for deleting and editing when in editing-mode and touching the delete-circle that is provided automatically?
Is it possible to remove the delete-circle altogether? Using "UITableViewCellEditingStyle.None" also disables the swipe-functionality.
Thanks in advance!
To avoid the round red delete button that appears when you put set UITableView isEditing to true at the left and does nothing when you click it, the minimum that worked for me was this (Swift 4, iOS 11)
// Avoid the round red delete button on the left of the cell:
func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return .none
}
I also have these functions, which probably interact:
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return savedTempTable.isEditing
}
// Including this function in the delegate enable left-swipe deleting
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath)
{
if editingStyle == .delete {
savedConversions.remove(at: indexPath.row)
}
}
// Including this function enables reordering
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath,to destinationIndexPath: IndexPath)
{
let elem = savedConversions.remove(at: sourceIndexPath.row)
savedConversions.insert(elem, at: destinationIndexPath.row)
}
override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return .none
}
override func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}
Although people can delete a row through swipe the delete-button in editing mode should not be removed. People may not know about the swipe gesture and by removing the delete button (which they already expect in editing mode) the app becomes more difficult to use.
If you really want to remove the delete button then you have to implement the delegate method tableView(_:editingStyleForRowAtIndexPath:). There you can return .None while the screen is in editing mode and .Delete while the screen is not.
To enable reordering you have to implement the data source methods tableView(_:canMoveRowAtIndexPath:) and tableView(_:moveRowAtIndexPath:toIndexPath:).
You follow this way to remove the delete Icon while editing:
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewCellAccessoryNone;
}
I have a UITableViewController displaying dynamic table data with an additional row at the end (using a separate cell prototype) containing an 'Add' button.
I'd like for users to be able to re-order the table rows but prevent them from moving a row to a point after the last row.
I've implemented:
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return indexPath.row != elements.count
}
To prevent users moving the 'Add' table row
and am also testing for
if(toIndexPath.row < library.regularTasks.count)
inside
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath)
which prevents the rows being swapped in the model.
However I can't see a way to prevent the rows being dragged beyond the last row in the UI
Found it!
I used:
override func tableView(tableView: UITableView, targetIndexPathForMoveFromRowAtIndexPath sourceIndexPath: NSIndexPath, toProposedIndexPath proposedDestinationIndexPath: NSIndexPath) -> NSIndexPath {
// Test whether destination is allowed
if(proposedDestinationIndexPath.row < elements.count){
return proposedDestinationIndexPath // if allowed move to proposed destination
}else{
return sourceIndexPath // if not, send back to where it came from!
}
}