Call moveRowAt method in didSelectRowAt? - swift

Is there a way that you can call
func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to toIndexPath: IndexPath) {
let affectedEvent = arrayMoved[fromIndexPath.row]
arrayMoved.remove(at: fromIndexPath.row)
arrayMoved.insert(affectedEvent, at: toIndexPath.row) }
in
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){}

tableView(_:moveRowAt:to:) is a delegate method, meaning it is a method that you should implement and let the system call you, not the other way around — normally you should not call a delegate method yourself.
If you want to tell the system to move a row, simply call moveRow(at:to:) of the table view, e.g.
func tableView(_ tableView: UITableView, didSelectRowAt ip: IndexPath) {
tableView.moveRow(at: ip, to: IndexPath(row: 0, section: ip.section))
}
After communicating with OP, want OP actually wants to reorder the model to push the selected item to the end. The typical way to do this is something like:
func tableView(_ tableView: UITableView, didSelectRowAt ip: IndexPath) {
// update the model.
model[ip.row].value = maxOfValue + 1
sortModelAgain()
// reload the model (note: no animation if using this)
tableView.reloadData()
}
or, if you'd like to manually keep the view and model in sync:
func tableView(_ tableView: UITableView, didSelectRowAt ip: IndexPath) {
// update the model.
model[ip.row].value = maxOfValue + 1
sortModelAgain()
// change the view to keep in sync of data.
tableView.beginUpdates()
let endRow = tableView.numberOfRows(inSection: ip.section) - 1
tableView.moveRow(at: ip, to: IndexPath(row: endRow, section: ip.section))
tableView.endUpdates()
}

Related

how to prevent a cell in tableview to be moved

I need to prevent last cell from second section from being moved and even to show the "right handle" that appears when tableview is editing.
I create cellsObject based upon a model which has an "identity" property in a Table with two cells. when using
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {}
I move from one array to the other based upon the section.
how and where should I block to that cell with that identity from being moved anywhere? I tried this inside cellForRow:
if model.identity == "DoNotMove" l {
cell.isEditing = false
cell.shouldIndentWhileEditing = false
cell.editingAccessoryType = .none
}
but is not working, tested the same inside the method
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {}
with crash result
Implement the data source method tableView(_:canMoveRowAt:)
func tableView(_ tableView: UITableView,
canMoveRowAt indexPath: IndexPath) -> Bool
and return false for the index path

didSelectRowAtIndexpath not responding to clicks

I'm making a revision app for high school students. In this view, the user should be able to select the units that they want to study for a certain subject, and the index path of the selected units will be stored in an int array and passed on to the next view for displaying images. Unfortunately, the didSelectRowAt method is not responding for some reason.
The delegate and data source are set correctly, I know that it is not getting called as I wrote a print statement in the function, and nothing was printed in the console when I click on any one the table cells.
var units = [String]()
var selectedRows = [Int]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return units.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "unitCell", for: indexPath) as! UnitCell
cell.textLabel?.text = units[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedRows.append(indexPath.row)
print(selectedRows)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destination = segue.destination as! ImageView
destination.folderNames = selectedRows
}
I expect an int array of row indexes of selected cells. But right now it is just empty.
If the code your showing in your question is accurate, the signature of the didSelectRowAt method is incorrect. It should be:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
Note the leading "_" for the first parameter. If your class is a UITableViewController, you'll also need to add an override keyword.
If your code is already using this signature, please update your question to reflect that.
Also, this leading code cannot be correct. Please update it to what you're actually using,
var units = String var selectedRows = Int
You should use delegate method
optional func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath)
Instead of your existing one
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath)
Try and share your results.
First thing is that your didSectRow is depricated so please use
below one
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
Secondly You have to set your TableView Delegate to Self like below
tableView.delegate = self

How to fix 'black background after deletion of one row"

If a row is deleted, tableView shows black area below cells, while tableView has white background color as with the cell view.
Look at this:
https://www.dropbox.com/s/55ssb73t0ngr9yj/screenshot.png?dl=0
After deleting a row (it can be any one of them, not necessarily the last one), suddenly, black area shows up, though I didn't change any constraint or height of the tableView. Also, behind tableView, there is nothing in this area other than the 'self.view' whose background is also white, and in front of table view, no view is positioned. (one view is there, but it is the size of the screen, so it cannot be black only for this area.)
extension ApptDetailViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return appt.places.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ApptDetailCell", for: indexPath) as! ApptDetailCell
cell.placeNumLabel.text = "Place \(indexPath.row + 1)"
cell.placeNameLabel.text = appt.places[indexPath.row]
return cell
}
}
extension ApptDetailViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 60
}
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let moveString = appt.places.remove(at: sourceIndexPath.row)
let moveBool = appt.reachedPlaces.remove(at: sourceIndexPath.row)
appt.places.insert(moveString, at: destinationIndexPath.row)
appt.reachedPlaces.insert(moveBool, at: destinationIndexPath.row)
print("appt.places: \(appt.places)")
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// deletion occurred.
appt.places.remove(at: indexPath.row)
appt.reachedPlaces.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .right)
}
}
}
As per our comment discussion —You can debug your UI using the view heirarchy debugger. This helps pinpoint anomalies in your views.
Or try to change the tableview background color.

How can I move tableview section?

I am developing the application with swift. I stored the objection data named Categories. I've added the tableViewImage here and there is no problem here. I want to move the section of the tableview together with the cell, but it does not. The functions I wrote are below. Please help me.Thanks.
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_tableview:UITableView, moveRowAtIndexPath sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath)
{
let temp = categories[sourceIndexPath.section]
categories[sourceIndexPath.section] = categories[destinationIndexPath.section];
categories[destinationIndexPath.section] = temp
}
func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return .none
}
You can try using this method, assigning the position of the section you want to move and the place where you want it to be at the end:
table.moveSection(0, toSection: 1)
You could also try deleting the section in the IndexSet or appropriate position, subtracting in 1 the number of sections of the table and then reinserting the section and increasing the sections by 1
let index = IndexSet(integer: 0)
self.number_sections -= 1
table.deleteSections(index, with: .fade)
let newIndex = IndexSet(integer: 1)
self.number_sections += 1
table.insertSections(newIndex, with: .fade)

Table View: right to left swipe to delete does not show up - swift 3

I've built a simple toDoList app with Swift 3. Now I want to be able to delete my items from a TableView by swiping from right to left. This code is what I've found. But nothing happens when I swipe to the left.
CODE:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return toDoList.count
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "Cell")
cell.textLabel?.text = toDoList[indexPath.row]
return cell
}
//
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if (editingStyle == .delete) {
toDoList.remove(at: indexPath.row)
UserDefaults.standard.set(toDoList, forKey: "toDoList")
tableView.reloadData()
}
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return .delete
}
This still does not work. Nothing happens when I swipe to the left. The to do List itself is working. I can add items to the table but I just can't remove them.
Thanks :)
Did you implement tableView:canEditRowAtIndexPath: method?
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
EDIT:
Thanks to #rmaddy for mentioning that the default value of tableView:canEditRowAtIndexPath: is true, implementing it doesn't solve the problem.
I'm not pretty sure of what are you trying to do from your code snippet, so make sure that you are implementing the following methods (UITableViewDelegate):
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if (editingStyle == .delete) {
toDoList.remove(at: indexPath.row)
UserDefaults.standard.set(toDoList, forKey: "toDoList")
tableView.reloadData()
}
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return .delete
}
You can also keep the implementation of tableView:canEditRowAtIndexPath: method:
Asks the data source to verify that the given row is editable.
So, -for example- if you want to let the first row is not editable, i.e user cannot swipe and delete the first row, you should do somthing like:
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
if indexPath.row == 0 {
return false
}
return true
}
Make sure that the UITableViewDataSource and UITableViewDelegate are connected with the ViewController.